Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / media_galleries / fileapi / iphoto_data_provider_browsertest.cc
blob10f1ebb5480110704cd41e8a8b71df04ee0fddfe
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 <string>
6 #include <vector>
8 #include "base/bind.h"
9 #include "base/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/format_macros.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/run_loop.h"
17 #include "base/stl_util.h"
18 #include "base/strings/stringprintf.h"
19 #include "chrome/browser/media_galleries/fileapi/iphoto_data_provider.h"
20 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
21 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
22 #include "chrome/test/base/in_process_browser_test.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "url/gurl.h"
26 using base::FilePath;
28 namespace iphoto {
30 class TestIPhotoDataProvider : public IPhotoDataProvider {
31 public:
32 TestIPhotoDataProvider(const base::FilePath& xml_library_path,
33 const base::Closure& callback)
34 : IPhotoDataProvider(xml_library_path),
35 callback_(callback) {
37 virtual ~TestIPhotoDataProvider() {}
39 private:
40 virtual void OnLibraryChanged(const base::FilePath& path,
41 bool error) OVERRIDE {
42 IPhotoDataProvider::OnLibraryChanged(path, error);
43 callback_.Run();
46 base::Closure callback_;
48 DISALLOW_COPY_AND_ASSIGN(TestIPhotoDataProvider);
51 class IPhotoDataProviderTest : public InProcessBrowserTest {
52 public:
53 IPhotoDataProviderTest() {}
54 virtual ~IPhotoDataProviderTest() {}
56 protected:
57 virtual void SetUp() OVERRIDE {
58 ASSERT_TRUE(library_dir_.CreateUniqueTempDir());
59 WriteLibraryInternal();
60 // The ImportedMediaGalleryRegistry is created on which ever thread calls
61 // GetInstance() first. It shouldn't matter what thread creates, however
62 // in practice it is always created on the UI thread, so this calls
63 // GetInstance here to mirror those real conditions.
64 ImportedMediaGalleryRegistry::GetInstance();
65 InProcessBrowserTest::SetUp();
68 void RunTest() {
69 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
70 base::RunLoop loop;
71 quit_closure_ = loop.QuitClosure();
72 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
73 FROM_HERE,
74 base::Bind(&IPhotoDataProviderTest::StartTestOnMediaTaskRunner,
75 base::Unretained(this)));
76 loop.Run();
79 void WriteLibrary(const base::Closure& callback) {
80 SetLibraryChangeCallback(callback);
81 WriteLibraryInternal();
84 void SetLibraryChangeCallback(const base::Closure& callback) {
85 EXPECT_TRUE(library_changed_callback_.is_null());
86 library_changed_callback_ = callback;
89 IPhotoDataProvider* data_provider() const {
90 return ImportedMediaGalleryRegistry::IPhotoDataProvider();
93 const base::FilePath& library_dir() const {
94 return library_dir_.path();
97 base::FilePath XmlFile() const {
98 return library_dir_.path().AppendASCII("library.xml");
101 // Start the test. The data provider is refreshed before calling StartTest
102 // and the result of the refresh is passed in.
103 virtual void StartTest(bool parse_success) = 0;
105 void TestDone() {
106 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
107 ImportedMediaGalleryRegistry* imported_registry =
108 ImportedMediaGalleryRegistry::GetInstance();
109 imported_registry->iphoto_data_provider_.reset();
110 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
111 quit_closure_);
114 // Override to provide a full library string.
115 virtual std::string GetLibraryString() {
116 return "<plist><dict>\n</dict></plist>\n";
119 private:
120 void StartTestOnMediaTaskRunner() {
121 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
122 ImportedMediaGalleryRegistry* imported_registry =
123 ImportedMediaGalleryRegistry::GetInstance();
124 imported_registry->iphoto_data_provider_.reset(
125 new TestIPhotoDataProvider(
126 XmlFile(),
127 base::Bind(&IPhotoDataProviderTest::OnLibraryChanged,
128 base::Unretained(this))));
129 data_provider()->RefreshData(base::Bind(&IPhotoDataProviderTest::StartTest,
130 base::Unretained(this)));
133 void OnLibraryChanged() {
134 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
135 if (!library_changed_callback_.is_null()) {
136 library_changed_callback_.Run();
137 library_changed_callback_.Reset();
141 void WriteLibraryInternal() {
142 std::string xml = GetLibraryString();
143 ASSERT_EQ(static_cast<int>(xml.size()),
144 file_util::WriteFile(XmlFile(), xml.c_str(), xml.size()));
147 base::ScopedTempDir library_dir_;
149 base::Closure library_changed_callback_;
151 base::Closure quit_closure_;
153 DISALLOW_COPY_AND_ASSIGN(IPhotoDataProviderTest);
156 class IPhotoDataProviderBasicTest : public IPhotoDataProviderTest {
157 public:
158 IPhotoDataProviderBasicTest() {}
159 virtual ~IPhotoDataProviderBasicTest() {}
161 virtual std::string GetLibraryString() OVERRIDE {
162 return "<plist><dict>\n"
163 "<key>List of Albums</key>\n"
164 "<array>"
165 " <dict>\n"
166 " <key>AlbumId</key>"
167 " <integer>14</integer>"
168 " <key>AlbumName</key>"
169 " <string>Album1</string>"
170 " <key>KeyList</key>"
171 " <array>"
172 " <string>1</string>"
173 " <string>3</string>" // [3] and [4] are name dupes
174 " <string>4</string>"
175 " </array>"
176 " </dict>\n"
177 " <dict>\n"
178 " <key>AlbumId</key>"
179 " <integer>15</integer>"
180 " <key>AlbumName</key>"
181 " <string>Album2</string>"
182 " <key>KeyList</key>"
183 " <array>"
184 " <string>2</string>"
185 " </array>"
186 " </dict>\n"
187 " <dict>\n"
188 " <key>AlbumId</key>"
189 " <integer>16</integer>"
190 " <key>AlbumName</key>"
191 " <string>Album5</string>"
192 " <key>KeyList</key>"
193 " <array>"
194 " <string>5</string>" // A name dupe of [2], but in another album.
195 " </array>"
196 " </dict>\n"
197 "</array>\n"
198 "<key>Master Image List</key>\n"
199 "<dict>\n"
200 " <key>1</key>\n"
201 " <dict>\n"
202 " <key>MediaType</key>"
203 " <string>Image</string>"
204 " <key>Caption</key>"
205 " <string>caption</string>"
206 " <key>GUID</key>\n"
207 " <string>guid1</string>"
208 " <key>ImagePath</key>"
209 " <string>/vol/path1.jpg</string>"
210 " <key>ThumbPath</key>"
211 " <string>/vol/thumb1.jpg</string>"
212 " </dict>\n"
213 " <key>2</key>\n"
214 " <dict>\n"
215 " <key>MediaType</key>"
216 " <string>Image</string>"
217 " <key>Caption</key>"
218 " <string>caption2</string>"
219 " <key>GUID</key>\n"
220 " <string>guid2</string>"
221 " <key>ImagePath</key>"
222 " <string>/vol/path2.jpg</string>"
223 " <key>ThumbPath</key>"
224 " <string>/vol/thumb2.jpg</string>"
225 " </dict>\n"
226 " <key>3</key>\n"
227 " <dict>\n"
228 " <key>MediaType</key>"
229 " <string>Image</string>"
230 " <key>Caption</key>"
231 " <string>caption3</string>"
232 " <key>GUID</key>\n"
233 " <string>guid3</string>"
234 " <key>ImagePath</key>"
235 " <string>/vol/path3.jpg</string>"
236 " <key>ThumbPath</key>"
237 " <string>/vol/thumb3.jpg</string>"
238 " </dict>\n"
239 " <key>4</key>\n" // A name duplicate of [3] in another path.
240 " <dict>\n"
241 " <key>MediaType</key>"
242 " <string>Image</string>"
243 " <key>Caption</key>"
244 " <string>caption</string>"
245 " <key>GUID</key>\n"
246 " <string>guid3</string>"
247 " <key>ImagePath</key>"
248 " <string>/vol/dupe/path3.jpg</string>"
249 " <key>ThumbPath</key>"
250 " <string>/vol/dupe/thumb3.jpg</string>"
251 " </dict>\n"
252 " <key>5</key>\n" // A name duplicate of [2] in another path.
253 " <dict>\n"
254 " <key>MediaType</key>"
255 " <string>Image</string>"
256 " <key>Caption</key>"
257 " <string>caption5</string>"
258 " <key>GUID</key>\n"
259 " <string>guid2</string>"
260 " <key>ImagePath</key>"
261 " <string>/vol/dupe/path2.jpg</string>"
262 " <key>ThumbPath</key>"
263 " <string>/vol/dupe/thumb2.jpg</string>"
264 " <key>OriginalPath</key>" \
265 " <string>/original/vol/another2.jpg</string>" \
266 " </dict>\n"
267 "</dict>\n"
268 "</dict></plist>\n";
271 virtual void StartTest(bool parse_success) OVERRIDE {
272 EXPECT_TRUE(parse_success);
274 std::vector<std::string> names = data_provider()->GetAlbumNames();
275 EXPECT_EQ(3U, names.size());
276 EXPECT_EQ("Album1", names[0]);
278 EXPECT_EQ(FilePath("/vol/path1.jpg").value(),
279 data_provider()->GetPhotoLocationInAlbum(
280 "Album1", "path1.jpg").value());
281 EXPECT_EQ(FilePath("/vol/path3.jpg").value(),
282 data_provider()->GetPhotoLocationInAlbum(
283 "Album1", "path3.jpg").value());
284 EXPECT_EQ(FilePath("/vol/dupe/path3.jpg").value(),
285 data_provider()->GetPhotoLocationInAlbum(
286 "Album1", "path3(4).jpg").value());
287 EXPECT_EQ(FilePath().value(),
288 data_provider()->GetPhotoLocationInAlbum(
289 "Album1", "path5.jpg").value());
291 // path2.jpg is name-duped, but in different albums, and so should not
292 // be mangled.
293 EXPECT_EQ(FilePath("/vol/dupe/path2.jpg").value(),
294 data_provider()->GetPhotoLocationInAlbum(
295 "Album5", "path2.jpg").value());
296 EXPECT_EQ(FilePath("/vol/path2.jpg").value(),
297 data_provider()->GetPhotoLocationInAlbum(
298 "Album2", "path2.jpg").value());
300 std::map<std::string, base::FilePath> photos =
301 data_provider()->GetAlbumContents("nonexistent");
302 EXPECT_EQ(0U, photos.size());
303 photos = data_provider()->GetAlbumContents("Album1");
304 EXPECT_EQ(3U, photos.size());
305 EXPECT_TRUE(ContainsKey(photos, "path1.jpg"));
306 EXPECT_FALSE(ContainsKey(photos, "path2.jpg"));
307 EXPECT_TRUE(ContainsKey(photos, "path3.jpg"));
308 EXPECT_TRUE(ContainsKey(photos, "path3(4).jpg"));
309 EXPECT_EQ(FilePath("/vol/path1.jpg").value(), photos["path1.jpg"].value());
310 EXPECT_EQ(FilePath("/vol/path3.jpg").value(),
311 photos["path3.jpg"].value());
312 EXPECT_EQ(FilePath("/vol/dupe/path3.jpg").value(),
313 photos["path3(4).jpg"].value());
315 photos = data_provider()->GetAlbumContents("Album2");
316 EXPECT_EQ(1U, photos.size());
317 EXPECT_TRUE(ContainsKey(photos, "path2.jpg"));
319 EXPECT_FALSE(data_provider()->HasOriginals("Album1"));
320 EXPECT_TRUE(data_provider()->HasOriginals("Album5"));
321 std::map<std::string, base::FilePath> originals =
322 data_provider()->GetOriginals("Album1");
323 EXPECT_EQ(0U, originals.size());
324 originals = data_provider()->GetOriginals("Album5");
325 EXPECT_EQ(1U, originals.size());
326 EXPECT_TRUE(ContainsKey(originals, "path2.jpg"));
327 EXPECT_FALSE(ContainsKey(originals, "path1.jpg"));
328 EXPECT_EQ(FilePath("/original/vol/another2.jpg").value(),
329 originals["path2.jpg"].value());
330 base::FilePath original_path =
331 data_provider()->GetOriginalPhotoLocation("Album5", "path2.jpg");
332 EXPECT_EQ(FilePath("/original/vol/another2.jpg").value(),
333 original_path.value());
335 TestDone();
338 private:
339 DISALLOW_COPY_AND_ASSIGN(IPhotoDataProviderBasicTest);
342 class IPhotoDataProviderRefreshTest : public IPhotoDataProviderTest {
343 public:
344 IPhotoDataProviderRefreshTest() {}
345 virtual ~IPhotoDataProviderRefreshTest() {}
347 std::string another_album;
349 virtual std::string GetLibraryString() OVERRIDE {
350 return "<plist><dict>\n"
351 "<key>List of Albums</key>\n"
352 "<array>"
353 " <dict>"
354 " <key>AlbumId</key>"
355 " <integer>14</integer>"
356 " <key>AlbumName</key>"
357 " <string>Album1</string>"
358 " <key>KeyList</key>"
359 " <array>"
360 " <string>1</string>"
361 " </array>"
362 " </dict>\n" +
363 another_album +
364 "</array>\n"
365 "<key>Master Image List</key>\n"
366 "<dict>\n"
367 " <key>1</key>\n"
368 " <dict>\n"
369 " <key>MediaType</key>"
370 " <string>Image</string>"
371 " <key>Caption1</key>"
372 " <string>caption</string>"
373 " <key>GUID</key>\n"
374 " <string>guid1</string>"
375 " <key>ImagePath</key>"
376 " <string>/vol/path1.jpg</string>"
377 " <key>ThumbPath</key>"
378 " <string>/vol/thumb1.jpg</string>"
379 " </dict>\n"
380 "</dict>\n"
381 "</dict></plist>\n";
384 virtual void StartTest(bool parse_success) OVERRIDE {
385 EXPECT_TRUE(parse_success);
387 EXPECT_EQ(FilePath("/vol/path1.jpg"),
388 data_provider()->GetPhotoLocationInAlbum("Album1", "path1.jpg"));
389 std::vector<std::string> names = data_provider()->GetAlbumNames();
390 EXPECT_EQ(1U, names.size());
391 EXPECT_EQ("Album1", names[0]);
393 another_album =
394 " <dict>"
395 " <key>AlbumId</key>"
396 " <integer>14</integer>"
397 " <key>AlbumName</key>"
398 " <string>Another Album</string>"
399 " <key>KeyList</key>"
400 " <array>"
401 " <string>1</string>"
402 " </array>"
403 " </dict>\n";
405 WriteLibrary(base::Bind(&IPhotoDataProviderRefreshTest::CheckAfterWrite,
406 base::Unretained(this)));
409 void CheckAfterWrite() {
410 // No change -- data has not been parsed.
411 EXPECT_EQ(FilePath("/vol/path1.jpg"),
412 data_provider()->GetPhotoLocationInAlbum("Album1", "path1.jpg"));
413 std::vector<std::string> names = data_provider()->GetAlbumNames();
414 EXPECT_EQ(1U, names.size());
415 EXPECT_EQ("Album1", names[0]);
417 data_provider()->RefreshData(
418 base::Bind(&IPhotoDataProviderRefreshTest::CheckRefresh,
419 base::Unretained(this)));
422 void CheckRefresh(bool is_valid) {
423 EXPECT_TRUE(is_valid);
425 EXPECT_EQ(FilePath("/vol/path1.jpg"),
426 data_provider()->GetPhotoLocationInAlbum("Album1", "path1.jpg"));
427 std::vector<std::string> names = data_provider()->GetAlbumNames();
428 EXPECT_EQ(2U, names.size());
429 if (names.size() == 2U) {
430 EXPECT_EQ("Album1", names[0]);
431 EXPECT_EQ("Another Album", names[1]);
434 TestDone();
437 private:
438 DISALLOW_COPY_AND_ASSIGN(IPhotoDataProviderRefreshTest);
441 class IPhotoDataProviderInvalidTest : public IPhotoDataProviderTest {
442 public:
443 IPhotoDataProviderInvalidTest() {}
444 virtual ~IPhotoDataProviderInvalidTest() {}
446 virtual void StartTest(bool parse_success) OVERRIDE {
447 EXPECT_TRUE(parse_success);
449 SetLibraryChangeCallback(
450 base::Bind(&IPhotoDataProvider::RefreshData,
451 base::Unretained(data_provider()),
452 base::Bind(&IPhotoDataProviderInvalidTest::CheckInvalid,
453 base::Unretained(this))));
454 EXPECT_EQ(1L, file_util::WriteFile(XmlFile(), " ", 1));
457 void CheckInvalid(bool is_valid) {
458 EXPECT_FALSE(is_valid);
459 TestDone();
462 private:
463 DISALLOW_COPY_AND_ASSIGN(IPhotoDataProviderInvalidTest);
466 IN_PROC_BROWSER_TEST_F(IPhotoDataProviderBasicTest, BasicTest) {
467 RunTest();
470 IN_PROC_BROWSER_TEST_F(IPhotoDataProviderRefreshTest, RefreshTest) {
471 RunTest();
474 IN_PROC_BROWSER_TEST_F(IPhotoDataProviderInvalidTest, InvalidTest) {
475 RunTest();
478 } // namespace iphoto