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/google_apis/drive_api_parser.h"
6
7#include "base/time/time.h"
8#include "base/values.h"
9#include "chrome/browser/google_apis/gdata_wapi_parser.h"
10#include "chrome/browser/google_apis/test_util.h"
11#include "chrome/browser/google_apis/time_util.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace google_apis {
15
16// Test about resource parsing.
17TEST(DriveAPIParserTest, AboutResourceParser) {
18  std::string error;
19  scoped_ptr<base::Value> document = test_util::LoadJSONFile(
20      "drive/about.json");
21  ASSERT_TRUE(document.get());
22
23  ASSERT_EQ(base::Value::TYPE_DICTIONARY, document->GetType());
24  scoped_ptr<AboutResource> resource(new AboutResource());
25  EXPECT_TRUE(resource->Parse(*document));
26
27  EXPECT_EQ("0AIv7G8yEYAWHUk9123", resource->root_folder_id());
28  EXPECT_EQ(5368709120LL, resource->quota_bytes_total());
29  EXPECT_EQ(1073741824LL, resource->quota_bytes_used());
30  EXPECT_EQ(8177LL, resource->largest_change_id());
31}
32
33TEST(DriveAPIParserTest, AboutResourceFromAccountMetadata) {
34  AccountMetadata account_metadata;
35  // Set up AccountMetadata instance.
36  {
37    account_metadata.set_quota_bytes_total(10000);
38    account_metadata.set_quota_bytes_used(1000);
39    account_metadata.set_largest_changestamp(100);
40  }
41
42  scoped_ptr<AboutResource> about_resource(
43      AboutResource::CreateFromAccountMetadata(account_metadata,
44                                               "dummy_root_id"));
45
46  EXPECT_EQ(10000, about_resource->quota_bytes_total());
47  EXPECT_EQ(1000, about_resource->quota_bytes_used());
48  EXPECT_EQ(100, about_resource->largest_change_id());
49  EXPECT_EQ("dummy_root_id", about_resource->root_folder_id());
50}
51
52// Test app list parsing.
53TEST(DriveAPIParserTest, AppListParser) {
54  std::string error;
55  scoped_ptr<base::Value> document = test_util::LoadJSONFile(
56      "drive/applist.json");
57  ASSERT_TRUE(document.get());
58
59  ASSERT_EQ(base::Value::TYPE_DICTIONARY, document->GetType());
60  scoped_ptr<AppList> applist(new AppList);
61  EXPECT_TRUE(applist->Parse(*document));
62
63  EXPECT_EQ("\"Jm4BaSnCWNND-noZsHINRqj4ABC/tuqRBw0lvjUdPtc_2msA1tN4XYZ\"",
64            applist->etag());
65  ASSERT_EQ(2U, applist->items().size());
66  // Check Drive app 1
67  const AppResource& app1 = *applist->items()[0];
68  EXPECT_EQ("123456788192", app1.application_id());
69  EXPECT_EQ("Drive app 1", app1.name());
70  EXPECT_EQ("", app1.object_type());
71  EXPECT_TRUE(app1.supports_create());
72  EXPECT_TRUE(app1.supports_import());
73  EXPECT_TRUE(app1.is_installed());
74  EXPECT_FALSE(app1.is_authorized());
75  EXPECT_EQ("https://chrome.google.com/webstore/detail/"
76            "abcdefghabcdefghabcdefghabcdefgh",
77            app1.product_url().spec());
78
79  ASSERT_EQ(1U, app1.primary_mimetypes().size());
80  EXPECT_EQ("application/vnd.google-apps.drive-sdk.123456788192",
81            *app1.primary_mimetypes()[0]);
82
83  ASSERT_EQ(2U, app1.secondary_mimetypes().size());
84  EXPECT_EQ("text/html", *app1.secondary_mimetypes()[0]);
85  EXPECT_EQ("text/plain", *app1.secondary_mimetypes()[1]);
86
87  ASSERT_EQ(2U, app1.primary_file_extensions().size());
88  EXPECT_EQ("exe", *app1.primary_file_extensions()[0]);
89  EXPECT_EQ("com", *app1.primary_file_extensions()[1]);
90
91  EXPECT_EQ(0U, app1.secondary_file_extensions().size());
92
93  ASSERT_EQ(6U, app1.icons().size());
94  const DriveAppIcon& icon1 = *app1.icons()[0];
95  EXPECT_EQ(DriveAppIcon::APPLICATION, icon1.category());
96  EXPECT_EQ(10, icon1.icon_side_length());
97  EXPECT_EQ("http://www.example.com/10.png", icon1.icon_url().spec());
98
99  const DriveAppIcon& icon6 = *app1.icons()[5];
100  EXPECT_EQ(DriveAppIcon::SHARED_DOCUMENT, icon6.category());
101  EXPECT_EQ(16, icon6.icon_side_length());
102  EXPECT_EQ("http://www.example.com/ds16.png", icon6.icon_url().spec());
103
104  // Check Drive app 2
105  const AppResource& app2 = *applist->items()[1];
106  EXPECT_EQ("876543210000", app2.application_id());
107  EXPECT_EQ("Drive app 2", app2.name());
108  EXPECT_EQ("", app2.object_type());
109  EXPECT_FALSE(app2.supports_create());
110  EXPECT_FALSE(app2.supports_import());
111  EXPECT_TRUE(app2.is_installed());
112  EXPECT_FALSE(app2.is_authorized());
113  EXPECT_EQ("https://chrome.google.com/webstore/detail/"
114            "hgfedcbahgfedcbahgfedcbahgfedcba",
115            app2.product_url().spec());
116
117  ASSERT_EQ(3U, app2.primary_mimetypes().size());
118  EXPECT_EQ("image/jpeg", *app2.primary_mimetypes()[0]);
119  EXPECT_EQ("image/png", *app2.primary_mimetypes()[1]);
120  EXPECT_EQ("application/vnd.google-apps.drive-sdk.876543210000",
121            *app2.primary_mimetypes()[2]);
122
123  EXPECT_EQ(0U, app2.secondary_mimetypes().size());
124  EXPECT_EQ(0U, app2.primary_file_extensions().size());
125  EXPECT_EQ(0U, app2.secondary_file_extensions().size());
126
127  ASSERT_EQ(3U, app2.icons().size());
128  const DriveAppIcon& icon2 = *app2.icons()[1];
129  EXPECT_EQ(DriveAppIcon::DOCUMENT, icon2.category());
130  EXPECT_EQ(10, icon2.icon_side_length());
131  EXPECT_EQ("http://www.example.com/d10.png", icon2.icon_url().spec());
132}
133
134TEST(DriveAPIParserTest, AppListFromAccountMetadata) {
135  AccountMetadata account_metadata;
136  // Set up AccountMetadata instance.
137  {
138    ScopedVector<InstalledApp> installed_apps;
139    scoped_ptr<InstalledApp> installed_app(new InstalledApp);
140    installed_app->set_app_id("app_id");
141    installed_app->set_app_name("name");
142    installed_app->set_object_type("object_type");
143    installed_app->set_supports_create(true);
144
145    {
146      ScopedVector<Link> links;
147      scoped_ptr<Link> link(new Link);
148      link->set_type(Link::LINK_PRODUCT);
149      link->set_href(GURL("http://product/url"));
150      links.push_back(link.release());
151      installed_app->set_links(&links);
152    }
153    {
154      ScopedVector<std::string> primary_mimetypes;
155      primary_mimetypes.push_back(new std::string("primary_mimetype"));
156      installed_app->set_primary_mimetypes(&primary_mimetypes);
157    }
158    {
159      ScopedVector<std::string> secondary_mimetypes;
160      secondary_mimetypes.push_back(new std::string("secondary_mimetype"));
161      installed_app->set_secondary_mimetypes(&secondary_mimetypes);
162    }
163    {
164      ScopedVector<std::string> primary_extensions;
165      primary_extensions.push_back(new std::string("primary_extension"));
166      installed_app->set_primary_extensions(&primary_extensions);
167    }
168    {
169      ScopedVector<std::string> secondary_extensions;
170      secondary_extensions.push_back(new std::string("secondary_extension"));
171      installed_app->set_secondary_extensions(&secondary_extensions);
172    }
173    {
174      ScopedVector<AppIcon> app_icons;
175      scoped_ptr<AppIcon> app_icon(new AppIcon);
176      app_icon->set_category(AppIcon::ICON_DOCUMENT);
177      app_icon->set_icon_side_length(10);
178      {
179        ScopedVector<Link> links;
180        scoped_ptr<Link> link(new Link);
181        link->set_type(Link::LINK_ICON);
182        link->set_href(GURL("http://icon/url"));
183        links.push_back(link.release());
184        app_icon->set_links(&links);
185      }
186      app_icons.push_back(app_icon.release());
187      installed_app->set_app_icons(&app_icons);
188    }
189
190    installed_apps.push_back(installed_app.release());
191    account_metadata.set_installed_apps(&installed_apps);
192  }
193
194  scoped_ptr<AppList> app_list(
195      AppList::CreateFromAccountMetadata(account_metadata));
196  const ScopedVector<AppResource>& items = app_list->items();
197  ASSERT_EQ(1U, items.size());
198
199  const AppResource& app_resource = *items[0];
200  EXPECT_EQ("app_id", app_resource.application_id());
201  EXPECT_EQ("name", app_resource.name());
202  EXPECT_EQ("object_type", app_resource.object_type());
203  EXPECT_TRUE(app_resource.supports_create());
204  EXPECT_EQ("http://product/url", app_resource.product_url().spec());
205  const ScopedVector<std::string>& primary_mimetypes =
206      app_resource.primary_mimetypes();
207  ASSERT_EQ(1U, primary_mimetypes.size());
208  EXPECT_EQ("primary_mimetype", *primary_mimetypes[0]);
209  const ScopedVector<std::string>& secondary_mimetypes =
210      app_resource.secondary_mimetypes();
211  ASSERT_EQ(1U, secondary_mimetypes.size());
212  EXPECT_EQ("secondary_mimetype", *secondary_mimetypes[0]);
213  const ScopedVector<std::string>& primary_file_extensions =
214      app_resource.primary_file_extensions();
215  ASSERT_EQ(1U, primary_file_extensions.size());
216  EXPECT_EQ("primary_extension", *primary_file_extensions[0]);
217  const ScopedVector<std::string>& secondary_file_extensions =
218      app_resource.secondary_file_extensions();
219  ASSERT_EQ(1U, secondary_file_extensions.size());
220  EXPECT_EQ("secondary_extension", *secondary_file_extensions[0]);
221
222  const ScopedVector<DriveAppIcon>& icons = app_resource.icons();
223  ASSERT_EQ(1U, icons.size());
224  const DriveAppIcon& icon = *icons[0];
225  EXPECT_EQ(DriveAppIcon::DOCUMENT, icon.category());
226  EXPECT_EQ(10, icon.icon_side_length());
227  EXPECT_EQ("http://icon/url", icon.icon_url().spec());
228}
229
230// Test file list parsing.
231TEST(DriveAPIParserTest, FileListParser) {
232  std::string error;
233  scoped_ptr<base::Value> document = test_util::LoadJSONFile(
234      "drive/filelist.json");
235  ASSERT_TRUE(document.get());
236
237  ASSERT_EQ(base::Value::TYPE_DICTIONARY, document->GetType());
238  scoped_ptr<FileList> filelist(new FileList);
239  EXPECT_TRUE(filelist->Parse(*document));
240
241  EXPECT_EQ("\"WtRjAPZWbDA7_fkFjc5ojsEvDEF/zyHTfoHpnRHovyi8bWpwK0DXABC\"",
242            filelist->etag());
243  EXPECT_EQ("EAIaggELEgA6egpi96It9mH_____f_8AAP__AAD_okhU-cHLz83KzszMxsjMzs_Ry"
244            "NGJnridyrbHs7u9tv8AAP__AP7__n__AP8AokhU-cHLz83KzszMxsjMzs_RyNGJnr"
245            "idyrbHs7u9tv8A__4QZCEiXPTi_wtIgTkAAAAAngnSXUgCDEAAIgsJPgart10AAAA"
246            "ABC", filelist->next_page_token());
247  EXPECT_EQ(GURL("https://www.googleapis.com/drive/v2/files?pageToken=EAIaggEL"
248                 "EgA6egpi96It9mH_____f_8AAP__AAD_okhU-cHLz83KzszMxsjMzs_RyNGJ"
249                 "nridyrbHs7u9tv8AAP__AP7__n__AP8AokhU-cHLz83KzszMxsjMzs_RyNGJ"
250                 "nridyrbHs7u9tv8A__4QZCEiXPTi_wtIgTkAAAAAngnSXUgCDEAAIgsJPgar"
251                 "t10AAAAABC"), filelist->next_link());
252
253  ASSERT_EQ(3U, filelist->items().size());
254  // Check file 1 (a regular file)
255  const FileResource& file1 = *filelist->items()[0];
256  EXPECT_EQ("0B4v7G8yEYAWHUmRrU2lMS2hLABC", file1.file_id());
257  EXPECT_EQ("\"WtRjAPZWbDA7_fkFjc5ojsEvDEF/MTM0MzM2NzgwMDIXYZ\"",
258            file1.etag());
259  EXPECT_EQ("My first file data", file1.title());
260  EXPECT_EQ("application/octet-stream", file1.mime_type());
261
262  EXPECT_FALSE(file1.labels().is_starred());
263  EXPECT_FALSE(file1.labels().is_hidden());
264  EXPECT_FALSE(file1.labels().is_trashed());
265  EXPECT_FALSE(file1.labels().is_restricted());
266  EXPECT_TRUE(file1.labels().is_viewed());
267
268  base::Time created_time;
269  ASSERT_TRUE(
270      util::GetTimeFromString("2012-07-24T08:51:16.570Z", &created_time));
271  EXPECT_EQ(created_time, file1.created_date());
272
273  base::Time modified_time;
274  ASSERT_TRUE(
275      util::GetTimeFromString("2012-07-27T05:43:20.269Z", &modified_time));
276  EXPECT_EQ(modified_time, file1.modified_date());
277  EXPECT_EQ(modified_time, file1.modified_by_me_date());
278
279  ASSERT_EQ(1U, file1.parents().size());
280  EXPECT_EQ("0B4v7G8yEYAWHYW1OcExsUVZLABC", file1.parents()[0]->file_id());
281  EXPECT_EQ(GURL("https://www.googleapis.com/drive/v2/files/"
282                 "0B4v7G8yEYAWHYW1OcExsUVZLABC"),
283            file1.parents()[0]->parent_link());
284  EXPECT_FALSE(file1.parents()[0]->is_root());
285
286  EXPECT_EQ(GURL("https://www.example.com/download"), file1.download_url());
287  EXPECT_EQ("ext", file1.file_extension());
288  EXPECT_EQ("d41d8cd98f00b204e9800998ecf8427e", file1.md5_checksum());
289  EXPECT_EQ(1000U, file1.file_size());
290
291  EXPECT_EQ(GURL("https://www.googleapis.com/drive/v2/files/"
292                 "0B4v7G8yEYAWHUmRrU2lMS2hLABC"),
293            file1.self_link());
294  EXPECT_EQ(GURL("https://docs.google.com/file/d/"
295                 "0B4v7G8yEYAWHUmRrU2lMS2hLABC/edit"),
296            file1.alternate_link());
297  EXPECT_EQ(GURL("https://docs.google.com/uc?"
298                 "id=0B4v7G8yEYAWHUmRrU2lMS2hLABC&export=download"),
299            file1.web_content_link());
300  ASSERT_EQ(1U, file1.open_with_links().size());
301  EXPECT_EQ("1234567890", file1.open_with_links()[0].app_id);
302  EXPECT_EQ(GURL("http://open_with_link/url"),
303            file1.open_with_links()[0].open_url);
304
305  // Check file 2 (a Google Document)
306  const FileResource& file2 = *filelist->items()[1];
307  EXPECT_EQ("Test Google Document", file2.title());
308  EXPECT_EQ("application/vnd.google-apps.document", file2.mime_type());
309
310  EXPECT_TRUE(file2.labels().is_starred());
311  EXPECT_TRUE(file2.labels().is_hidden());
312  EXPECT_TRUE(file2.labels().is_trashed());
313  EXPECT_TRUE(file2.labels().is_restricted());
314  EXPECT_TRUE(file2.labels().is_viewed());
315  base::Time shared_with_me_time;
316  ASSERT_TRUE(util::GetTimeFromString("2012-07-27T04:54:11.030Z",
317                                      &shared_with_me_time));
318  EXPECT_EQ(shared_with_me_time, file2.shared_with_me_date());
319
320  EXPECT_EQ(0U, file2.file_size());
321
322  ASSERT_EQ(0U, file2.parents().size());
323
324  EXPECT_EQ(GURL("https://docs.google.com/a/chromium.org/document/d/"
325                 "1Pc8jzfU1ErbN_eucMMqdqzY3eBm0v8sxXm_1CtLxABC/preview"),
326            file2.embed_link());
327  EXPECT_EQ(GURL("https://docs.google.com/feeds/vt?gd=true&"
328                 "id=1Pc8jzfU1ErbN_eucMMqdqzY3eBm0v8sxXm_1CtLxABC&"
329                 "v=3&s=AMedNnoAAAAAUBJyB0g8HbxZaLRnlztxefZPS24LiXYZ&sz=s220"),
330            file2.thumbnail_link());
331  EXPECT_EQ(0U, file2.open_with_links().size());
332
333  // Check file 3 (a folder)
334  const FileResource& file3 = *filelist->items()[2];
335  EXPECT_EQ(0U, file3.file_size());
336  EXPECT_EQ("TestFolder", file3.title());
337  EXPECT_EQ("application/vnd.google-apps.folder", file3.mime_type());
338  ASSERT_TRUE(file3.IsDirectory());
339
340  ASSERT_EQ(1U, file3.parents().size());
341  EXPECT_EQ("0AIv7G8yEYAWHUk9ABC", file3.parents()[0]->file_id());
342  EXPECT_TRUE(file3.parents()[0]->is_root());
343  EXPECT_EQ(0U, file3.open_with_links().size());
344}
345
346// Test change list parsing.
347TEST(DriveAPIParserTest, ChangeListParser) {
348  std::string error;
349  scoped_ptr<base::Value> document =
350      test_util::LoadJSONFile("drive/changelist.json");
351  ASSERT_TRUE(document.get());
352
353  ASSERT_EQ(base::Value::TYPE_DICTIONARY, document->GetType());
354  scoped_ptr<ChangeList> changelist(new ChangeList);
355  EXPECT_TRUE(changelist->Parse(*document));
356
357  EXPECT_EQ("\"Lp2bjAtLP341hvGmYHhxjYyBPJ8/BWbu_eylt5f_aGtCN6mGRv9hABC\"",
358            changelist->etag());
359  EXPECT_EQ("8929", changelist->next_page_token());
360  EXPECT_EQ("https://www.googleapis.com/drive/v2/changes?pageToken=8929",
361            changelist->next_link().spec());
362  EXPECT_EQ(13664, changelist->largest_change_id());
363
364  ASSERT_EQ(4U, changelist->items().size());
365
366  const ChangeResource& change1 = *changelist->items()[0];
367  EXPECT_EQ(8421, change1.change_id());
368  EXPECT_FALSE(change1.is_deleted());
369  EXPECT_EQ("1Pc8jzfU1ErbN_eucMMqdqzY3eBm0v8sxXm_1CtLxABC", change1.file_id());
370  EXPECT_EQ(change1.file_id(), change1.file()->file_id());
371
372  scoped_ptr<ResourceEntry> entry1(
373      ResourceEntry::CreateFromChangeResource(change1));
374  EXPECT_EQ(change1.file_id(), entry1->resource_id());
375  EXPECT_EQ(change1.is_deleted(), entry1->deleted());
376
377  const ChangeResource& change2 = *changelist->items()[1];
378  EXPECT_EQ(8424, change2.change_id());
379  EXPECT_FALSE(change2.is_deleted());
380  EXPECT_EQ("0B4v7G8yEYAWHUmRrU2lMS2hLABC", change2.file_id());
381  EXPECT_EQ(change2.file_id(), change2.file()->file_id());
382
383  scoped_ptr<ResourceEntry> entry2(
384      ResourceEntry::CreateFromChangeResource(change2));
385  EXPECT_EQ(change2.file_id(), entry2->resource_id());
386  EXPECT_EQ(change2.is_deleted(), entry2->deleted());
387
388  const ChangeResource& change3 = *changelist->items()[2];
389  EXPECT_EQ(8429, change3.change_id());
390  EXPECT_FALSE(change3.is_deleted());
391  EXPECT_EQ("0B4v7G8yEYAWHYW1OcExsUVZLABC", change3.file_id());
392  EXPECT_EQ(change3.file_id(), change3.file()->file_id());
393
394  scoped_ptr<ResourceEntry> entry3(
395      ResourceEntry::CreateFromChangeResource(change3));
396  EXPECT_EQ(change3.file_id(), entry3->resource_id());
397  EXPECT_EQ(change3.is_deleted(), entry3->deleted());
398
399  // Deleted entry.
400  const ChangeResource& change4 = *changelist->items()[3];
401  EXPECT_EQ(8430, change4.change_id());
402  EXPECT_EQ("ABCv7G8yEYAWHc3Y5X0hMSkJYXYZ", change4.file_id());
403  EXPECT_TRUE(change4.is_deleted());
404
405  scoped_ptr<ResourceEntry> entry4(
406      ResourceEntry::CreateFromChangeResource(change4));
407  EXPECT_EQ(change4.file_id(), entry4->resource_id());
408  EXPECT_EQ(change4.is_deleted(), entry4->deleted());
409}
410
411TEST(DriveAPIParserTest, HasKind) {
412  scoped_ptr<base::Value> change_list_json(
413      test_util::LoadJSONFile("drive/changelist.json"));
414  scoped_ptr<base::Value> file_list_json(
415      test_util::LoadJSONFile("drive/filelist.json"));
416
417  EXPECT_TRUE(ChangeList::HasChangeListKind(*change_list_json));
418  EXPECT_FALSE(ChangeList::HasChangeListKind(*file_list_json));
419
420  EXPECT_FALSE(FileList::HasFileListKind(*change_list_json));
421  EXPECT_TRUE(FileList::HasFileListKind(*file_list_json));
422}
423
424}  // namespace google_apis
425