- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / media_galleries / fileapi / iphoto_data_provider_browsertest.cc
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 <string>
6 #include <vector>
7
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"
25
26 using base::FilePath;
27
28 namespace iphoto {
29
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) {
36   }
37   virtual ~TestIPhotoDataProvider() {}
38
39  private:
40   virtual void OnLibraryChanged(const base::FilePath& path,
41                                 bool error) OVERRIDE {
42     IPhotoDataProvider::OnLibraryChanged(path, error);
43     callback_.Run();
44   }
45
46   base::Closure callback_;
47
48   DISALLOW_COPY_AND_ASSIGN(TestIPhotoDataProvider);
49 };
50
51 class IPhotoDataProviderTest : public InProcessBrowserTest {
52  public:
53   IPhotoDataProviderTest() {}
54   virtual ~IPhotoDataProviderTest() {}
55
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();
66   }
67
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();
77   }
78
79   void WriteLibrary(const base::Closure& callback) {
80     SetLibraryChangeCallback(callback);
81     WriteLibraryInternal();
82   }
83
84   void SetLibraryChangeCallback(const base::Closure& callback) {
85     EXPECT_TRUE(library_changed_callback_.is_null());
86     library_changed_callback_ = callback;
87   }
88
89   IPhotoDataProvider* data_provider() const {
90     return ImportedMediaGalleryRegistry::IPhotoDataProvider();
91   }
92
93   const base::FilePath& library_dir() const {
94     return library_dir_.path();
95   }
96
97   base::FilePath XmlFile() const {
98     return library_dir_.path().AppendASCII("library.xml");
99   }
100
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;
104
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_);
112   }
113
114   // Override to provide a full library string.
115   virtual std::string GetLibraryString() {
116     return "<plist><dict>\n</dict></plist>\n";
117   }
118
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)));
131   };
132
133   void OnLibraryChanged() {
134     DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
135     if (!library_changed_callback_.is_null()) {
136       library_changed_callback_.Run();
137       library_changed_callback_.Reset();
138     }
139   }
140
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()));
145   }
146
147   base::ScopedTempDir library_dir_;
148
149   base::Closure library_changed_callback_;
150
151   base::Closure quit_closure_;
152
153   DISALLOW_COPY_AND_ASSIGN(IPhotoDataProviderTest);
154 };
155
156 class IPhotoDataProviderBasicTest : public IPhotoDataProviderTest {
157  public:
158   IPhotoDataProviderBasicTest() {}
159   virtual ~IPhotoDataProviderBasicTest() {}
160
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       "  </dict>\n"
265       "</dict>\n"
266       "</dict></plist>\n";
267   }
268
269   virtual void StartTest(bool parse_success) OVERRIDE {
270     EXPECT_TRUE(parse_success);
271
272     std::vector<std::string> names = data_provider()->GetAlbumNames();
273     EXPECT_EQ(3U, names.size());
274     EXPECT_EQ("Album1", names[0]);
275
276     EXPECT_EQ(FilePath("/vol/path1.jpg").value(),
277               data_provider()->GetPhotoLocationInAlbum(
278                   "Album1", "path1.jpg").value());
279     EXPECT_EQ(FilePath("/vol/path3.jpg").value(),
280               data_provider()->GetPhotoLocationInAlbum(
281                   "Album1", "path3.jpg").value());
282     EXPECT_EQ(FilePath("/vol/dupe/path3.jpg").value(),
283               data_provider()->GetPhotoLocationInAlbum(
284                   "Album1", "path3(4).jpg").value());
285     EXPECT_EQ(FilePath().value(),
286               data_provider()->GetPhotoLocationInAlbum(
287                   "Album1", "path5.jpg").value());
288
289     // path2.jpg is name-duped, but in different albums, and so should not
290     // be mangled.
291     EXPECT_EQ(FilePath("/vol/dupe/path2.jpg").value(),
292               data_provider()->GetPhotoLocationInAlbum(
293                   "Album5", "path2.jpg").value());
294     EXPECT_EQ(FilePath("/vol/path2.jpg").value(),
295               data_provider()->GetPhotoLocationInAlbum(
296                   "Album2", "path2.jpg").value());
297
298     std::map<std::string, base::FilePath> photos =
299         data_provider()->GetAlbumContents("nonexistent");
300     EXPECT_EQ(0U, photos.size());
301     photos = data_provider()->GetAlbumContents("Album1");
302     EXPECT_EQ(3U, photos.size());
303     EXPECT_TRUE(ContainsKey(photos, "path1.jpg"));
304     EXPECT_FALSE(ContainsKey(photos, "path2.jpg"));
305     EXPECT_TRUE(ContainsKey(photos, "path3.jpg"));
306     EXPECT_TRUE(ContainsKey(photos, "path3(4).jpg"));
307     EXPECT_EQ(FilePath("/vol/path1.jpg").value(), photos["path1.jpg"].value());
308     EXPECT_EQ(FilePath("/vol/path3.jpg").value(),
309         photos["path3.jpg"].value());
310     EXPECT_EQ(FilePath("/vol/dupe/path3.jpg").value(),
311         photos["path3(4).jpg"].value());
312
313     photos = data_provider()->GetAlbumContents("Album2");
314     EXPECT_EQ(1U, photos.size());
315     EXPECT_TRUE(ContainsKey(photos, "path2.jpg"));
316
317     TestDone();
318   }
319
320  private:
321   DISALLOW_COPY_AND_ASSIGN(IPhotoDataProviderBasicTest);
322 };
323
324 class IPhotoDataProviderRefreshTest : public IPhotoDataProviderTest {
325  public:
326   IPhotoDataProviderRefreshTest() {}
327   virtual ~IPhotoDataProviderRefreshTest() {}
328
329   std::string another_album;
330
331   virtual std::string GetLibraryString() OVERRIDE {
332     return "<plist><dict>\n"
333       "<key>List of Albums</key>\n"
334       "<array>"
335       "    <dict>"
336       "      <key>AlbumId</key>"
337       "      <integer>14</integer>"
338       "      <key>AlbumName</key>"
339       "      <string>Album1</string>"
340       "      <key>KeyList</key>"
341       "      <array>"
342       "      <string>1</string>"
343       "      </array>"
344       "    </dict>\n" +
345       another_album +
346       "</array>\n"
347       "<key>Master Image List</key>\n"
348       "<dict>\n"
349       "  <key>1</key>\n"
350       "  <dict>\n"
351       "    <key>MediaType</key>"
352       "    <string>Image</string>"
353       "    <key>Caption1</key>"
354       "    <string>caption</string>"
355       "    <key>GUID</key>\n"
356       "    <string>guid1</string>"
357       "    <key>ImagePath</key>"
358       "    <string>/vol/path1.jpg</string>"
359       "    <key>ThumbPath</key>"
360       "    <string>/vol/thumb1.jpg</string>"
361       "  </dict>\n"
362       "</dict>\n"
363       "</dict></plist>\n";
364   }
365
366   virtual void StartTest(bool parse_success) OVERRIDE {
367     EXPECT_TRUE(parse_success);
368
369     EXPECT_EQ(FilePath("/vol/path1.jpg"),
370               data_provider()->GetPhotoLocationInAlbum("Album1", "path1.jpg"));
371     std::vector<std::string> names = data_provider()->GetAlbumNames();
372     EXPECT_EQ(1U, names.size());
373     EXPECT_EQ("Album1", names[0]);
374
375     another_album =
376       "    <dict>"
377       "      <key>AlbumId</key>"
378       "      <integer>14</integer>"
379       "      <key>AlbumName</key>"
380       "      <string>Another Album</string>"
381       "      <key>KeyList</key>"
382       "      <array>"
383       "      <string>1</string>"
384       "      </array>"
385       "    </dict>\n";
386
387     WriteLibrary(base::Bind(&IPhotoDataProviderRefreshTest::CheckAfterWrite,
388                             base::Unretained(this)));
389   }
390
391   void CheckAfterWrite() {
392     // No change -- data has not been parsed.
393     EXPECT_EQ(FilePath("/vol/path1.jpg"),
394               data_provider()->GetPhotoLocationInAlbum("Album1", "path1.jpg"));
395     std::vector<std::string> names = data_provider()->GetAlbumNames();
396     EXPECT_EQ(1U, names.size());
397     EXPECT_EQ("Album1", names[0]);
398
399     data_provider()->RefreshData(
400         base::Bind(&IPhotoDataProviderRefreshTest::CheckRefresh,
401                    base::Unretained(this)));
402   }
403
404   void CheckRefresh(bool is_valid) {
405     EXPECT_TRUE(is_valid);
406
407     EXPECT_EQ(FilePath("/vol/path1.jpg"),
408               data_provider()->GetPhotoLocationInAlbum("Album1", "path1.jpg"));
409     std::vector<std::string> names = data_provider()->GetAlbumNames();
410     EXPECT_EQ(2U, names.size());
411     if (names.size() == 2U) {
412       EXPECT_EQ("Album1", names[0]);
413       EXPECT_EQ("Another Album", names[1]);
414     }
415
416     TestDone();
417   }
418
419  private:
420   DISALLOW_COPY_AND_ASSIGN(IPhotoDataProviderRefreshTest);
421 };
422
423 class IPhotoDataProviderInvalidTest : public IPhotoDataProviderTest {
424  public:
425   IPhotoDataProviderInvalidTest() {}
426   virtual ~IPhotoDataProviderInvalidTest() {}
427
428   virtual void StartTest(bool parse_success) OVERRIDE {
429     EXPECT_TRUE(parse_success);
430
431     SetLibraryChangeCallback(
432         base::Bind(&IPhotoDataProvider::RefreshData,
433                    base::Unretained(data_provider()),
434                    base::Bind(&IPhotoDataProviderInvalidTest::CheckInvalid,
435                               base::Unretained(this))));
436     EXPECT_EQ(1L, file_util::WriteFile(XmlFile(), " ", 1));
437   }
438
439   void CheckInvalid(bool is_valid) {
440     EXPECT_FALSE(is_valid);
441     TestDone();
442   }
443
444  private:
445   DISALLOW_COPY_AND_ASSIGN(IPhotoDataProviderInvalidTest);
446 };
447
448 IN_PROC_BROWSER_TEST_F(IPhotoDataProviderBasicTest, BasicTest) {
449   RunTest();
450 }
451
452 IN_PROC_BROWSER_TEST_F(IPhotoDataProviderRefreshTest, RefreshTest) {
453   RunTest();
454 }
455
456 IN_PROC_BROWSER_TEST_F(IPhotoDataProviderInvalidTest, InvalidTest) {
457   RunTest();
458 }
459
460 }  // namespace iphoto