/Source/externals/GData/Source/Tests/GDataFeedTest.m

http://google-email-uploader-mac.googlecode.com/ · Objective C · 2212 lines · 1440 code · 472 blank · 300 comment · 25 complexity · d08856f41ab760b3b32aadb99534327a MD5 · raw file

Large files are truncated click here to view the full file

  1. /* Copyright (c) 2007 Google Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. //
  16. // GDataFeedTest.m
  17. //
  18. #import "GData.h"
  19. #import "GDataFeedTest.h"
  20. #import "GDataElementsTest.h"
  21. #import "GDataEntryCalendarEvent.h"
  22. #import "GDataEntryYouTubeVideo.h"
  23. #import "GDataMapConstants.h"
  24. @implementation GDataFeedTest
  25. - (void)runTests:(TestKeyPathValues *)tests {
  26. // step through each feed test
  27. for (int testIndex = 0;
  28. tests[testIndex].str1 != nil;
  29. testIndex++) {
  30. // get the class of this feed and the path to the test file of xml data
  31. //
  32. // The class name may specify a service version, like GDataFeedCalendar/2.0,
  33. // and may have a "-ignoreUnknown" suffix indicating unknown elements should be
  34. // ignored, like GDataFeedCalendar-ignore/2.0
  35. NSString *className = tests[testIndex].str1;
  36. NSString *serviceVersion = nil;
  37. BOOL shouldIgnoreUnknowns = NO;
  38. NSArray *components = [className componentsSeparatedByString:@"/"];
  39. if ([components count] == 2) {
  40. className = [components objectAtIndex:0];
  41. serviceVersion = [components objectAtIndex:1];
  42. }
  43. if ([className hasSuffix:@"-ignoreUnknown"]) {
  44. shouldIgnoreUnknowns = YES;
  45. NSUInteger nameLen = [className length] - [@"-ignoreUnknown" length];
  46. className = [className substringToIndex:nameLen];
  47. }
  48. #ifdef GDATA_TARGET_NAMESPACE
  49. className = [NSString stringWithFormat:@"%s_%@",
  50. GDATA_TARGET_NAMESPACE_STRING, className];
  51. #endif
  52. Class gdataClass = NSClassFromString(className);
  53. STAssertNotNil(gdataClass, @"Cannot make class for class name: %@", className);
  54. NSString *feedPath = tests[testIndex].str2;
  55. NSData *data = [NSData dataWithContentsOfFile:feedPath];
  56. STAssertNotNil(data, @"Cannot read feed from %@", feedPath);
  57. // create the feed object
  58. GDataFeedBase *feed1 = nil;
  59. if ([gdataClass instancesRespondToSelector:@selector(initWithData:serviceVersion:)]) {
  60. feed1 = [[[gdataClass alloc] initWithData:data
  61. serviceVersion:serviceVersion
  62. shouldIgnoreUnknowns:shouldIgnoreUnknowns] autorelease];
  63. } else {
  64. // this "feed" isn't a proper feed, and might be an entry
  65. NSError *error = nil;
  66. NSXMLDocument *doc = [[[NSXMLDocument alloc] initWithData:data
  67. options:0
  68. error:&error] autorelease];
  69. STAssertNotNil(doc, @"Cannot allocate XML document for %@, error %@",
  70. feedPath, error);
  71. NSXMLElement* root = [doc rootElement];
  72. feed1 = [[[gdataClass alloc] initWithXMLElement:root
  73. parent:nil
  74. serviceVersion:serviceVersion
  75. surrogates:nil
  76. shouldIgnoreUnknowns:shouldIgnoreUnknowns] autorelease];
  77. }
  78. // copy the feed object
  79. GDataObject *feed1copy = [[feed1 copy] autorelease];
  80. STAssertTrue([feed1 isEqual:feed1copy], @"Failed copy feed (%@) from %@ to %@",
  81. feedPath, feed1, feed1copy);
  82. // make a new feed object we'll test against from XML generated by the copy
  83. NSXMLElement *outputXML = [feed1copy XMLElement];
  84. GDataFeedBase *feed2 = [[[gdataClass alloc] initWithXMLElement:outputXML
  85. parent:nil
  86. serviceVersion:serviceVersion
  87. surrogates:nil
  88. shouldIgnoreUnknowns:shouldIgnoreUnknowns] autorelease];
  89. STAssertTrue([feed2 isEqual:feed1copy], @"Failed for %@ using XML \n %@\n\nto convert\n %@ \nto\n %@",
  90. feedPath, outputXML, feed1copy, feed2);
  91. // generate a description; this can fire an exception for an invalid keyPath
  92. // in the description record list
  93. STAssertNotNil([feed2 description], @"Could not generate description for %@",
  94. feedPath);
  95. // step through all the key-value path tests
  96. while (1) {
  97. ++testIndex;
  98. NSString *keyPath = tests[testIndex].str1;
  99. NSString *expectedValue = tests[testIndex].str2;
  100. if (keyPath == nil || [keyPath length] == 0) break;
  101. #if GDATA_USES_LIBXML
  102. // skip the XMLStrings until we can normalize whitespace and closing
  103. // brackets and other minor differences
  104. if ([keyPath hasSuffix:@".XMLString"]) continue;
  105. #endif
  106. NSString *result = [GDataElementsTest valueInObject:feed2
  107. forKeyPathIncludingArrays:keyPath];
  108. // if the result wasn't a string but responds to stringValue, then
  109. // invoke that to get a string
  110. if ([expectedValue isKindOfClass:[NSString class]]
  111. && ![result isKindOfClass:[NSString class]]
  112. && [result respondsToSelector:@selector(stringValue)]) {
  113. result = [(id)result stringValue];
  114. }
  115. // we'll test for equality unless the expected result begins "hasPrefix:"
  116. // or "contains:"
  117. if ([expectedValue hasPrefix:@"hasPrefix:"]) {
  118. NSString *prefix = [expectedValue substringFromIndex:[@"hasPrefix:" length]];
  119. STAssertTrue([result hasPrefix:prefix], @"failed object %@ \n testing key path '%@' for prefix:\n %@ \n!= prefix:\n %@",
  120. feed2, keyPath, result, prefix);
  121. } else if ([expectedValue hasPrefix:@"contains:"]) {
  122. NSString *substring = [expectedValue substringFromIndex:[@"contains:" length]];
  123. NSRange range = [result rangeOfString:substring];
  124. STAssertTrue(result != nil && range.location != NSNotFound,
  125. @"failed object %@ \n testing key path '%@' for substring:\n %@ \n!= contains:\n %@",
  126. feed2, keyPath, result, substring);
  127. } else {
  128. #ifdef GDATA_TARGET_NAMESPACE
  129. // tests for class name need the prefix added
  130. if ([keyPath hasSuffix:@"className"]
  131. && [expectedValue hasPrefix:@"GData"]) {
  132. expectedValue = [NSString stringWithFormat:@"%s_%@",
  133. GDATA_TARGET_NAMESPACE_STRING, expectedValue];
  134. }
  135. #endif
  136. STAssertTrue(AreEqualOrBothNil(result, expectedValue), @"failed object %@ \n testing key path '%@'\n %@ \n!= \n %@",
  137. feed2, keyPath, result, expectedValue);
  138. }
  139. }
  140. }
  141. }
  142. - (void)testBooksFeed {
  143. //
  144. // Volumes Feed
  145. //
  146. TestKeyPathValues tests[] =
  147. {
  148. { @"GDataFeedVolume", @"Tests/FeedBooksVolumesTest1.xml" },
  149. // GDataFeedVolume paths
  150. { @"identifier", @"http://www.google.com/books/feeds/users/1728172424007912469/volumes" },
  151. { @"authors.0.name", @"1728172424007912469" },
  152. // GDataEntryVolume paths
  153. { @"entries.0.creators.0", @"Jim Davis" },
  154. { @"entries.0.dates.0", @"2006-01-31" },
  155. { @"entries.0.volumeDescriptions.0", @"contains:Pig Out" },
  156. { @"entries.0.embeddability", kGDataBooksNotEmbeddable },
  157. { @"entries.0.openAccess", kGDataBooksEnabled },
  158. { @"entries.0.formats.0", @"93 pages" },
  159. { @"entries.0.volumeIdentifiers.0", @"_PRJAAAACAAJ" },
  160. { @"entries.0.volumeIdentifiers.1", @"ISBN:0345464664" },
  161. { @"entries.0.publishers.0", @"Ballantine Books" },
  162. { @"entries.0.subjects.0", @"Humor" },
  163. { @"entries.0.volumeTitles.0", @"Garfield Pigs Out" },
  164. { @"entries.0.viewability", kGDataBooksViewNoPages },
  165. { @"entries.0.thumbnailLink.href", @"hasPrefix:http://bks2.books.google.com/books?id=_PRJAAAACAAJ" },
  166. { @"entries.0.previewLink.href", @"contains:id=_PRJAAAACAAJ&ie=ISO-8859-1" },
  167. { @"entries.0.infoLink.href", @"contains:id=_PRJAAAACAAJ&ie=ISO-8859-1" },
  168. { @"entries.0.rating.value", @"3" },
  169. { @"entries.0.rating.average", @"2" },
  170. { @"entries.0.review", @"Ageless? No way." },
  171. { @"entries.0.contentVersion", @"1.2beta5" },
  172. { @"", @"" },
  173. { nil, nil }
  174. };
  175. [self runTests:tests];
  176. }
  177. - (void)testCalendarFeed {
  178. TestKeyPathValues tests[] =
  179. {
  180. //
  181. // Calendar Feed
  182. //
  183. { @"GDataFeedCalendar/2.0", @"Tests/FeedCalendarTest1.xml" },
  184. // GDataFeedCalendar paths
  185. { @"title", @"Fred Flintstone's Calendar List" },
  186. { @"links.1.rel", kGDataLinkRelPost },
  187. { @"links.2.rel", @"self" },
  188. { @"authors.0.name", @"Fred Flintstone" },
  189. { @"authors.0.email", @"fred@gmail.com" },
  190. { @"generator.URI", @"http://www.google.com/calendar" },
  191. { @"generator.name", @"Google Calendar" },
  192. { @"generator.version", @"1.0" },
  193. { @"startIndex", @"1" },
  194. { @"itemsPerPage", @"3" },
  195. { @"ETag", @"Nofzeigeritznum" },
  196. { @"fieldSelection", @"@gd:*,link" },
  197. { @"unknownAttributes.@count", @"0" },
  198. { @"unknownChildren.@count", @"0" },
  199. // GDataEntryCalendar paths
  200. { @"entries.0.identifier", @"http://www.google.com/calendar/feeds/test%40domain.net/test%40domain.net" },
  201. { @"entries.0.publishedDate.RFC3339String", @"2006-11-14T00:03:38Z" },
  202. { @"entries.0.updatedDate.RFC3339String", @"2006-11-09T00:16:10Z" },
  203. { @"entries.0.editedDate.RFC3339String", @"2006-11-09T00:16:15Z" },
  204. { @"entries.0.title", @"Fred Flintstone" },
  205. { @"entries.0.links.0.rel", @"alternate" },
  206. { @"entries.0.links.1.href", @"http://www.google.com/calendar/feeds/test%40domain.net/test%40domain.net" },
  207. { @"entries.0.authors.0.name", @"Fred Flintstone" },
  208. { @"entries.0.authors.0.email", @"fred@gmail.com" },
  209. { @"entries.0.isHidden", @"0" },
  210. { @"entries.0.timeZoneName", @"America/Los_Angeles" },
  211. { @"entries.0.timesCleaned", @"31" },
  212. { @"entries.0.color", @"#B1365F" },
  213. { @"entries.0.accessLevel", kGDataCalendarAccessOwner},
  214. { @"entries.0.overrideName", @"over-ride-name" },
  215. { @"entries.0.ETag", @"W/C04EQXc6fCp7ImA9WxZbGUU." },
  216. { @"entries.0.fieldSelection", @"@gd:*,title,gd:when" },
  217. { @"entries.1.locations.0", @"Joes Pub" },
  218. { @"entries.1.fieldSelection", nil },
  219. { @"entries.2.isSelected", @"0" },
  220. { @"entries.2.isHidden", @"1" },
  221. { @"entries.0.unknownAttributes.@count", @"0" },
  222. { @"entries.0.unknownChildren.@count", @"0" },
  223. { @"", @"" }, // end of feed
  224. //
  225. // CalendarEvent Feed
  226. //
  227. { @"GDataFeedCalendarEvent", @"Tests/FeedCalendarEventTest1.xml" },
  228. // GDataFeedCalendarEvent paths
  229. { @"title", @"Fred Flintstone" },
  230. { @"subtitle", @"Fred Flintstone" },
  231. { @"links.0.rel", kGDataLinkRelFeed },
  232. { @"links.2.rel", @"self" },
  233. { @"authors.0.name", @"Fred Flintstone" },
  234. { @"authors.0.email", @"fred@gmail.com" },
  235. { @"identifier", @"http://www.google.com/calendar/feeds/test%40gmail.com/private/full" },
  236. { @"namespaces.gCal", kGDataNamespaceGCal },
  237. { @"generator.URI", @"http://www.google.com/calendar" },
  238. { @"generator.name", @"Google Calendar" },
  239. { @"generator.version", @"1.0" },
  240. { @"startIndex", @"1" },
  241. { @"itemsPerPage", @"100000" },
  242. { @"timeZoneName", @"America/Los_Angeles" },
  243. { @"timesCleaned", @"7" },
  244. { @"unknownAttributes.@count", @"0" },
  245. { @"unknownChildren.@count", @"0" },
  246. // GDataEntryCalendarEvent paths
  247. { @"entries.0.identifier", @"contains:i12d4avieju0vogcga72aj3908" },
  248. { @"entries.0.publishedDate.RFC3339String", @"2006-10-27T22:48:14Z" },
  249. { @"entries.0.updatedDate.RFC3339String", @"2006-11-03T21:17:40Z" },
  250. { @"entries.0.title", @"3 days" },
  251. { @"entries.0.content", @"The description field" },
  252. { @"entries.0.links.0.title", @"alternate" },
  253. { @"entries.0.links.1.rel", @"self" },
  254. { @"entries.0.authors.0.name", @"Fred Flintstone" },
  255. { @"entries.0.authors.0.email", @"fred@gmail.com" },
  256. { @"entries.0.visibility", kGDataEventVisibilityDefault },
  257. { @"entries.0.comment.feedLink.href", @"contains:i12d4avieju0vogcga72aj3908/comments" },
  258. { @"entries.0.shouldSendEventNotifications", @"0" },
  259. { @"entries.0.isQuickAdd", @"0" },
  260. { @"entries.0.transparency", kGDataEventTransparencyOpaque },
  261. { @"entries.0.eventStatus", kGDataEventStatusConfirmed },
  262. { @"entries.0.participants.0.email", @"FredFlintstone@gmail.com" },
  263. { @"entries.0.participants.0.rel", kGDataWhoEventAttendee },
  264. { @"entries.0.participants.0.attendeeStatus", kGDataWhoAttendeeStatusDeclined },
  265. { @"entries.0.participants.1.numberOfAdditionalGuests", @"5" },
  266. { @"entries.0.participants.1.email", @"FredFlintstone@google.com" },
  267. { @"entries.0.participants.2.email", @"freg@gmail.com" },
  268. { @"entries.0.times.0.endTime.RFC3339String", @"2006-11-16" },
  269. { @"entries.0.times.0.reminders.0.minutes", @"10" },
  270. { @"entries.0.locations.0", @"The-where-field" },
  271. { @"entries.0.locations.0.rel", nil },
  272. { @"entries.0.sequenceNumber", @"2" },
  273. { @"entries.0.iCalUID", @"4A24A0FF-EA3A-4839-AA09-F4283CB6D345" },
  274. { @"entries.0.canGuestsModify", @"0" },
  275. { @"entries.0.canGuestsInviteOthers", @"0" },
  276. { @"entries.0.canGuestsSeeGuests", @"0" },
  277. { @"entries.0.canAnyoneAddSelf", @"0" },
  278. { @"entries.1.recurrence", @"hasPrefix:DTSTART;VALUE=DATE:20061120" },
  279. { @"entries.1.reminders.0.minutes", @"10" },
  280. { @"entries.1.isDeleted", @"0" },
  281. { @"entries.3.locations.0", @"Seattle" },
  282. { @"entries.3.isDeleted", @"1" },
  283. { @"entries.3.canGuestsModify", @"1" },
  284. { @"entries.3.canGuestsInviteOthers", @"1" },
  285. { @"entries.3.canGuestsSeeGuests", @"1" },
  286. { @"entries.3.canAnyoneAddSelf", @"1" },
  287. { @"entries.0.unknownAttributes.@count", @"0" },
  288. { @"entries.0.unknownChildren.@count", @"0" },
  289. { @"", @"" }, // end of feed
  290. //
  291. // CalendarEvent Feed with no entries
  292. //
  293. { @"GDataFeedCalendarEvent", @"Tests/FeedCalendarEventTest0.xml" },
  294. // GDataFeedCalendarEvent paths
  295. { @"title", @"Fred Flintstone" },
  296. { @"subtitle", @"Fred Flintstone" },
  297. { @"links.0.rel", kGDataLinkRelFeed },
  298. { @"links.2.rel", @"self" },
  299. { @"authors.0.name", @"Fred Flintstone" },
  300. { @"authors.0.email", @"fred@gmail.com" },
  301. { @"identifier", @"http://www.google.com/calendar/feeds/test%40gmail.com/private/full" },
  302. { @"namespaces.gCal", kGDataNamespaceGCal },
  303. { @"generator.URI", @"http://www.google.com/calendar" },
  304. { @"generator.name", @"Google Calendar" },
  305. { @"generator.version", @"1.0" },
  306. { @"startIndex", @"1" },
  307. { @"itemsPerPage", @"100000" },
  308. { @"timeZoneName", @"America/Los_Angeles" },
  309. { @"timesCleaned", @"7" },
  310. { @"unknownAttributes.@count", @"0" },
  311. { @"unknownChildren.@count", @"0" },
  312. // GDataEntryCalendarEvent paths
  313. { @"entries.@count", @"0" },
  314. { @"", @"" }, // end of feed
  315. { nil, nil } // end of test array
  316. };
  317. [self runTests:tests];
  318. }
  319. - (void)testContactsFeed {
  320. TestKeyPathValues tests[] =
  321. {
  322. //
  323. // Contact Feed
  324. //
  325. { @"GDataFeedContact/2.0", @"Tests/FeedContactTest1.xml" },
  326. // GDataFeedContact paths
  327. { @"title", @"Contacts" },
  328. { @"categories.0.term", kGDataCategoryContact },
  329. { @"links.1.rel", kGDataLinkRelPost },
  330. { @"unknownAttributes.@count.stringValue", @"0" },
  331. { @"unknownChildren.@count.stringValue", @"0" },
  332. // GDataEntryContact paths
  333. // First entry is real; second entry is deleted
  334. { @"entries.0.identifier", @"contains:9cfaae9" },
  335. { @"entries.0.categories.0.term", kGDataCategoryContact },
  336. { @"entries.0.isDeleted", @"0" },
  337. { @"entries.0.primaryOrganization.orgName", @"Le Company" },
  338. { @"entries.0.organizations.0.orgName", @"Le Company" },
  339. { @"entries.0.organizations.0.orgTitle", @"Titularstuff" },
  340. { @"entries.0.organizations.0.label", nil },
  341. { @"entries.0.organizations.0.rel", kGDataContactOther },
  342. { @"entries.0.organizations.0.isPrimary", @"1" },
  343. { @"entries.0.organizations.1.orgName", @"Deadhead Associates" },
  344. { @"entries.0.organizations.1.orgTitle", @"Groupie" },
  345. { @"entries.0.organizations.1.label", @"DAz" },
  346. { @"entries.0.organizations.1.rel", nil },
  347. { @"entries.0.organizations.1.isPrimary", @"0" },
  348. { @"entries.0.primaryIMAddress.address", @"fooaimz" },
  349. { @"entries.0.IMAddresses.0.protocol", kGDataIMProtocolAIM },
  350. { @"entries.0.IMAddresses.0.address", @"fooaimz" },
  351. { @"entries.0.IMAddresses.0.label", @"werkz" },
  352. { @"entries.0.IMAddresses.0.isPrimary", @"1" },
  353. { @"entries.0.IMAddresses.1.protocol", kGDataIMProtocolMSN },
  354. { @"entries.0.IMAddresses.1.address", @"foomsn" },
  355. { @"entries.0.IMAddresses.1.label", nil },
  356. { @"entries.0.IMAddresses.1.rel", kGDataContactHome },
  357. { @"entries.0.IMAddresses.1.isPrimary", @"0" },
  358. { @"entries.0.IMAddresses.2.protocol", kGDataIMProtocolGoogleTalk },
  359. { @"entries.0.IMAddresses.2.address", @"foo@gmail.com" },
  360. { @"entries.0.IMAddresses.2.label", nil },
  361. { @"entries.0.IMAddresses.2.rel", kGDataContactOther },
  362. { @"entries.0.IMAddresses.2.isPrimary", @"0" },
  363. { @"entries.0.IMAddresses.3.protocol", kGDataIMProtocolJabber },
  364. { @"entries.0.IMAddresses.3.address", @"foo@jabber.org" },
  365. { @"entries.0.IMAddresses.3.label", @"jabz" },
  366. { @"entries.0.IMAddresses.3.rel", nil },
  367. { @"entries.0.IMAddresses.3.isPrimary", @"0" },
  368. { @"entries.0.primaryPhoneNumber.stringValue", @"123-4567" },
  369. { @"entries.0.phoneNumbers.0.stringValue", @"123-4567" },
  370. { @"entries.0.phoneNumbers.0.label", nil },
  371. { @"entries.0.phoneNumbers.0.rel", kGDataPhoneNumberMobile },
  372. { @"entries.0.phoneNumbers.0.isPrimary", @"1" },
  373. { @"entries.0.phoneNumbers.1.stringValue", @"333-1414" },
  374. { @"entries.0.phoneNumbers.1.label", @"shoefone" },
  375. { @"entries.0.phoneNumbers.1.rel", nil },
  376. { @"entries.0.phoneNumbers.1.isPrimary", @"0" },
  377. { @"entries.0.primaryPostalAddress.stringValue", @"123 Lane St" },
  378. { @"entries.0.postalAddresses.0.stringValue", @"123 Lane St" },
  379. { @"entries.0.postalAddresses.0.label", nil },
  380. { @"entries.0.postalAddresses.0.rel", kGDataContactHome },
  381. { @"entries.0.postalAddresses.0.isPrimary", @"1" },
  382. { @"entries.0.primaryEmailAddress.address", @"foo@bar.com" },
  383. { @"entries.0.emailAddresses.0.address", @"foo@bar.com" },
  384. { @"entries.0.emailAddresses.0.label", nil },
  385. { @"entries.0.emailAddresses.0.rel", kGDataContactHome },
  386. { @"entries.0.emailAddresses.0.isPrimary", @"1" },
  387. { @"entries.0.emailAddresses.1.address", @"2@bar.com" },
  388. { @"entries.0.emailAddresses.1.label", @"norzglie" },
  389. { @"entries.0.emailAddresses.1.rel", nil },
  390. { @"entries.0.emailAddresses.1.isPrimary", @"0" },
  391. { @"entries.0.groupMembershipInfos.0.href", @"http://www.google.com/m8/feeds/contactGroups/user@gmail.com/full/2" },
  392. { @"entries.0.groupMembershipInfos.0.isDeleted", @"1" },
  393. { @"entries.0.extendedProperties.0.name", @"com.mycompany.myprop" },
  394. { @"entries.0.extendedProperties.0.value", @"zoop" },
  395. { @"entries.0.extendedProperties.0.XMLValues", nil },
  396. { @"entries.0.extendedProperties.1.name", @"com.mycompany.myprop2" },
  397. { @"entries.0.extendedProperties.1.value", nil },
  398. { @"entries.0.extendedProperties.1.XMLValues.0.XMLString", @"<myXML><myChild attr=\"nerf\"></myChild></myXML>" },
  399. { @"entries.0.extendedProperties.1.unknownChildren.@count.stringValue", @"0" },
  400. { @"entries.1.identifier", @"contains:b001135" },
  401. { @"entries.1.categories.0.term", kGDataCategoryContact },
  402. { @"entries.1.isDeleted", @"1" },
  403. { @"entries.0.unknownAttributes.@count.stringValue", @"0" },
  404. { @"entries.0.unknownChildren.@count.stringValue", @"0" },
  405. { @"", @"" }, // end of feed
  406. //
  407. // Contact Feed with V3 elements
  408. //
  409. { @"GDataFeedContact/3.0", @"Tests/FeedContactTest2.xml" },
  410. // GDataFeedContact paths
  411. { @"title", @"Fred Flintstone's Contacts" },
  412. { @"categories.0.term", kGDataCategoryContact },
  413. { @"ETag", @"W/\"DkYHQHgzfCt7ImA9WxJREEU.\"" },
  414. { @"unknownAttributes.@count.stringValue", @"0" },
  415. { @"unknownChildren.@count.stringValue", @"0" },
  416. // GDataEntryContact paths
  417. { @"entries.0.identifier", @"contains:754fdf0c0db53ab3" },
  418. { @"entries.0.categories.0.term", kGDataCategoryContact },
  419. { @"entries.0.isDeleted", @"0" },
  420. { @"entries.0.ETag", @"\"Rno_eTVSLyt7ImA9WxJREEUORwc.\"" },
  421. { @"entries.0.editedDate.RFC3339String", @"2009-05-11T23:20:37Z" },
  422. { @"entries.0.primaryOrganization.orgName", @"Acme Corp." },
  423. { @"entries.0.organizations.0.orgName", @"Acme Corp." },
  424. { @"entries.0.organizations.0.orgTitle", nil },
  425. { @"entries.0.organizations.0.label", nil },
  426. { @"entries.0.organizations.0.rel", kGDataContactWork },
  427. { @"entries.0.organizations.0.isPrimary", @"1" },
  428. { @"entries.0.primaryIMAddress.address", nil },
  429. { @"entries.0.IMAddresses.0.protocol", kGDataIMProtocolGoogleTalk },
  430. { @"entries.0.IMAddresses.0.address", @"fredsim@example.com" },
  431. { @"entries.0.IMAddresses.0.label", @"main messaging addr" },
  432. { @"entries.0.IMAddresses.0.rel", nil },
  433. { @"entries.0.IMAddresses.0.isPrimary", @"0" },
  434. { @"entries.0.primaryPhoneNumber.stringValue", @"425-555-1234" },
  435. { @"entries.0.phoneNumbers.0.stringValue", @"425-555-1234" },
  436. { @"entries.0.phoneNumbers.0.label", @"Grand Central" },
  437. { @"entries.0.phoneNumbers.0.rel", nil },
  438. { @"entries.0.phoneNumbers.0.isPrimary", @"1" },
  439. { @"entries.0.phoneNumbers.1.stringValue", @"425-555-0000" },
  440. { @"entries.0.phoneNumbers.1.label", nil },
  441. { @"entries.0.phoneNumbers.1.rel", kGDataPhoneNumberCar },
  442. { @"entries.0.phoneNumbers.1.isPrimary", @"0" },
  443. { @"entries.0.primaryStructuredPostalAddress.street", @"301 Cobblestone Way" },
  444. { @"entries.0.structuredPostalAddresses.0.street", @"301 Cobblestone Way" },
  445. { @"entries.0.structuredPostalAddresses.0.postCode", @"12345" },
  446. { @"entries.0.structuredPostalAddresses.0.formattedAddress", @"301 Cobblestone Way\nBedrock, CA 12345\nUnited States" },
  447. { @"entries.0.structuredPostalAddresses.0.region", @"CA" },
  448. { @"entries.0.structuredPostalAddresses.0.countryName", @"United States" },
  449. { @"entries.0.structuredPostalAddresses.0.label", nil },
  450. { @"entries.0.structuredPostalAddresses.0.rel", kGDataContactHome },
  451. { @"entries.0.structuredPostalAddresses.0.isPrimary", @"1" },
  452. { @"entries.0.primaryEmailAddress.address", @"fred@example.com" },
  453. { @"entries.0.emailAddresses.0.address", @"fred@example.com" },
  454. { @"entries.0.emailAddresses.0.label", nil },
  455. { @"entries.0.emailAddresses.0.rel", kGDataContactHome },
  456. { @"entries.0.emailAddresses.0.isPrimary", @"1" },
  457. { @"entries.0.groupMembershipInfos.0.href", @"http://www.google.com/m8/feeds/groups/fredflintstone%40example.com/base/6" },
  458. { @"entries.0.groupMembershipInfos.0.isDeleted", @"0" },
  459. { @"entries.0.extendedProperties.0.name", @"fredprop" },
  460. { @"entries.0.extendedProperties.0.value", @"12345" },
  461. { @"entries.0.extendedProperties.0.XMLValues", nil },
  462. { @"entries.0.billingInformation", @"account overdue" },
  463. { @"entries.0.birthday", @"1990-12-01" },
  464. { @"entries.0.birthdayDate.timeIntervalSince1970", @"660052800" },
  465. { @"entries.0.calendarLinks.0.rel", nil },
  466. { @"entries.0.calendarLinks.0.label", @"full calendar" },
  467. { @"entries.0.calendarLinks.0.href", @"http://www.google.com/calendar/render" },
  468. { @"entries.0.primaryCalendarLink.label", @"full calendar" },
  469. { @"entries.0.directoryServer", @"dir server" },
  470. // { @"entries.0.events.0", @"" },
  471. { @"entries.0.externalIDs.0.label", @"ext id" },
  472. { @"entries.0.externalIDs.0.rel", nil },
  473. { @"entries.0.externalIDs.0.stringValue", @"54321" },
  474. { @"entries.0.gender", @"male" },
  475. { @"entries.0.hobbies.0.stringValue", @"gurgling" },
  476. { @"entries.0.initials", @"F.F." },
  477. { @"entries.0.jots.0.rel", kGDataContactJotHome },
  478. { @"entries.0.jots.0.stringValue", @"1248" },
  479. // { @"entries.0.languages.0", @"" },
  480. { @"entries.0.maidenName", @"Marshovitzky" },
  481. { @"entries.0.mileage", @"42 miles" },
  482. { @"entries.0.name.fullName", @"Fred Flintstone" },
  483. { @"entries.0.name.givenName", @"Fred" },
  484. { @"entries.0.name.familyName", @"Flintstone" },
  485. { @"entries.0.nickname", @"Rocks" },
  486. { @"entries.0.occupation", @"TV Personality" },
  487. { @"entries.0.priority", kGDataContactPriorityLow },
  488. { @"entries.0.relations.0.rel", kGDataContactRelationPartner },
  489. { @"entries.0.relations.0.label", nil },
  490. { @"entries.0.relations.0.stringValue", @"Wilma" },
  491. { @"entries.0.sensitivity", kGDataContactSensitivityNormal },
  492. { @"entries.0.shortName", @"Freddy" },
  493. { @"entries.0.subject", @"subject val" },
  494. { @"entries.0.userDefinedFields.0.key", @"Cat" },
  495. { @"entries.0.userDefinedFields.0.stringValue", @"Cheezeburger" },
  496. { @"entries.0.websiteLinks.0.href", @"http://example.com/site.html" },
  497. { @"entries.0.websiteLinks.0.rel", kGDataContactWebsiteLinkHomePage },
  498. { @"entries.0.websiteLinks.0.label", nil },
  499. { @"entries.0.websiteLinks.0.isPrimary", @"0" },
  500. { @"entries.0.where", @"The Quarry" },
  501. { @"entries.0.unknownAttributes.@count.stringValue", @"0" },
  502. { @"entries.0.unknownChildren.@count.stringValue", @"0" },
  503. { @"", @"" }, // end of feed
  504. { nil, nil } // end of test array
  505. };
  506. [self runTests:tests];
  507. }
  508. - (void)testSpreadsheetFeeds {
  509. TestKeyPathValues tests[] =
  510. {
  511. //
  512. // Spreadsheet feed (list of user's spreadsheets)
  513. //
  514. { @"GDataFeedSpreadsheet", @"Tests/FeedSpreadsheetTest1.xml" },
  515. // feed paths
  516. { @"identifier", @"http://spreadsheets.google.com/feeds/spreadsheets/private/full" },
  517. { @"links.2.href", @"http://spreadsheets.google.com/feeds/spreadsheets/private/full?tfe=" },
  518. { @"title", @"Available Spreadsheets - test@foo.net" },
  519. { @"unknownAttributes.@count", @"0" },
  520. { @"unknownChildren.@count", @"0" },
  521. // entry paths
  522. // There is one entry
  523. { @"entries.0.identifier", @"http://spreadsheets.google.com/feeds/spreadsheets/private/full/o04181601172097104111.497668944883620000" },
  524. { @"entries.0.updatedDate.RFC3339String", @"2007-03-22T23:25:53Z" },
  525. { @"entries.0.categories.2.scheme", kGDataCategorySchemeSpreadsheet },
  526. { @"entries.0.categories.2.term", kGDataCategorySpreadsheet },
  527. { @"entries.0.title", @"My Test Spreadsheet" },
  528. { @"entries.0.unknownAttributes.@count", @"0" },
  529. { @"entries.0.unknownChildren.@count", @"1" },
  530. { @"", @"" }, // end of feed
  531. // repeat the test, with unknown children turned off
  532. { @"GDataFeedSpreadsheet-ignoreUnknown", @"Tests/FeedSpreadsheetTest1.xml" },
  533. // feed paths
  534. { @"identifier", @"http://spreadsheets.google.com/feeds/spreadsheets/private/full" },
  535. { @"unknownAttributes.@count", @"0" },
  536. { @"unknownChildren.@count", @"0" },
  537. // entry paths
  538. // There is one entry
  539. { @"entries.0.identifier", @"http://spreadsheets.google.com/feeds/spreadsheets/private/full/o04181601172097104111.497668944883620000" },
  540. { @"entries.0.updatedDate.RFC3339String", @"2007-03-22T23:25:53Z" },
  541. { @"entries.0.unknownAttributes.@count", @"0" },
  542. { @"entries.0.unknownChildren.@count", @"0" },
  543. { @"", @"" }, // end of feed
  544. //
  545. // Worksheet feed (list of a spreadsheet's worksheets)
  546. //
  547. { @"GDataFeedWorksheet", @"Tests/FeedSpreadsheetWorksheetTest1.xml" },
  548. // feed paths
  549. { @"identifier", @"http://spreadsheets.google.com/feeds/worksheets/o04181601172097104111.497668944883620000/private/full" },
  550. { @"links.2.href", @"http://spreadsheets.google.com/feeds/worksheets/o04181601172097104111.497668944883620000/private/full?tfe=" },
  551. { @"title", @"My Test Spreadsheet" },
  552. { @"authors.0.email", @"test@foo.net" },
  553. { @"unknownAttributes.@count", @"0" },
  554. { @"unknownChildren.@count", @"0" },
  555. // entry paths
  556. // There is one entry
  557. { @"entries.0.identifier", @"http://spreadsheets.google.com/feeds/worksheets/o04181601172097104111.497668944883620000/private/full/od6" },
  558. { @"entries.0.updatedDate.RFC3339String", @"2007-03-22T23:28:50Z" },
  559. { @"entries.0.categories.0.scheme", kGDataCategorySchemeSpreadsheet },
  560. { @"entries.0.categories.0.term", kGDataCategoryWorksheet },
  561. { @"entries.0.title", @"Sheet1" },
  562. { @"entries.0.rowCount", @"100" },
  563. { @"entries.0.columnCount", @"20" },
  564. { @"entries.0.unknownAttributes.@count", @"0" },
  565. { @"entries.0.unknownChildren.@count", @"0" },
  566. { @"", @"" }, // end of feed
  567. //
  568. // Cells feed (all of a worksheet's cells)
  569. //
  570. { @"GDataFeedSpreadsheetCell", @"Tests/FeedSpreadsheetCellsTest1.xml" },
  571. // feed paths
  572. { @"identifier", @"http://spreadsheets.google.com/feeds/cells/o04181601172097104111.497668944883620000/od6/private/full" },
  573. { @"links.0.href", @"http://spreadsheets.google.com/ccc?key=o04181601172097104111.497668944883620000" },
  574. { @"categories.0.scheme", kGDataCategorySchemeSpreadsheet },
  575. { @"categories.0.term", kGDataCategorySpreadsheetCell },
  576. { @"title", @"Sheet1" },
  577. { @"authors.0.email", @"test@foo.net" },
  578. { @"rowCount", @"100" },
  579. { @"columnCount", @"20" },
  580. { @"unknownAttributes.@count", @"0" },
  581. { @"unknownChildren.@count", @"0" },
  582. // entry paths
  583. // The sheet looks like this (2 cols x 4 rows)
  584. // Fred Martha
  585. // =pi() =sin(A2)
  586. // =1.5*pi() =sin(A3)
  587. // =2.0*pi() =sin(A4)
  588. { @"entries.1.identifier", @"http://spreadsheets.google.com/feeds/cells/o04181601172097104111.497668944883620000/od6/private/full/R1C2" },
  589. { @"entries.1.updatedDate.RFC3339String", @"2007-03-22T23:28:50Z" },
  590. { @"entries.1.categories.0.scheme", kGDataCategorySchemeSpreadsheet },
  591. { @"entries.1.categories.0.term", kGDataCategorySpreadsheetCell },
  592. { @"entries.1.title", @"B1" },
  593. { @"entries.1.cell.column", @"2" },
  594. { @"entries.1.cell.row", @"1" },
  595. { @"entries.1.cell.inputString", @"Martha" },
  596. { @"entries.1.cell.numericValue", nil },
  597. { @"entries.1.cell.resultString", @"Martha" },
  598. { @"entries.0.unknownAttributes.@count", @"0" },
  599. { @"entries.0.unknownChildren.@count", @"0" },
  600. { @"", @"" }, // end of feed
  601. //
  602. // List feed (all of a worksheet as a list) which contains customElements
  603. //
  604. // feed paths
  605. { @"GDataFeedSpreadsheetList", @"Tests/FeedSpreadsheetListTest1.xml" },
  606. { @"identifier", @"http://spreadsheets.google.com/feeds/list/o04181601172097104111.497668944883620000/od6/private/full" },
  607. { @"links.0.href", @"http://spreadsheets.google.com/ccc?key=o04181601172097104111.497668944883620000" },
  608. { @"categories.0.scheme", kGDataCategorySchemeSpreadsheet },
  609. { @"categories.0.term", kGDataCategorySpreadsheetList },
  610. { @"title", @"Sheet1" },
  611. { @"authors.0.email", @"test@foo.net" },
  612. { @"unknownAttributes.@count", @"0" },
  613. { @"unknownChildren.@count", @"0" },
  614. // entry paths
  615. { @"entries.1.customElementDictionary.fred", @"4.71238898038469" },
  616. { @"entries.1.customElementDictionary.martha", @"-1" },
  617. { @"entries.0.unknownAttributes.@count", @"0" },
  618. { @"entries.0.unknownChildren.@count", @"0" },
  619. { @"", @"" }, // end of feed
  620. //
  621. // Table feed
  622. //
  623. // feed paths
  624. { @"GDataFeedSpreadsheetTable", @"Tests/FeedSpreadsheetTableTest1.xml" },
  625. { @"identifier", @"http://spreadsheets.google.com/feeds/RRHuSwAKiaEGw526z3DVYw/tables" },
  626. { @"categories.0.scheme", kGDataCategoryScheme },
  627. { @"categories.0.term", kGDataCategorySpreadsheetTable },
  628. { @"title", @"Table of Doom" },
  629. { @"authors.0.email", @"fredflintstone@example.com" },
  630. { @"unknownAttributes.@count", @"0" },
  631. { @"unknownChildren.@count", @"0" },
  632. // entry paths
  633. { @"entries.0.content.sourceURI", @"http://spreadsheets.google.com/feeds/RRHuSwAKiaEGw526z3DVYw/records/1" },
  634. { @"entries.0.spreadsheetData.startIndex", @"4" },
  635. { @"entries.0.spreadsheetData.numberOfRows", @"3" },
  636. { @"entries.0.spreadsheetData.insertionMode", kGDataSpreadsheetModeInsert },
  637. { @"entries.0.spreadsheetData.columns.0.name", @"Column Beta" },
  638. { @"entries.0.spreadsheetData.columns.0.indexString", @"B" },
  639. { @"entries.0.spreadsheetHeader.row", @"3" },
  640. { @"entries.0.worksheetName", @"Sheet 1" },
  641. { @"entries.0.unknownAttributes.@count", @"0" },
  642. { @"entries.0.unknownChildren.@count", @"0" },
  643. { @"", @"" }, // end of feed
  644. //
  645. // Record feed
  646. //
  647. // feed paths
  648. { @"GDataFeedSpreadsheetRecord", @"Tests/FeedSpreadsheetRecordTest1.xml" },
  649. { @"identifier", @"http://spreadsheets.google.com/feeds/RRHuSwAKiaEGw526z3DVYw/records/1" },
  650. { @"categories.0.scheme", kGDataCategoryScheme },
  651. { @"categories.0.term", kGDataCategorySpreadsheetRecord },
  652. { @"title", @"Records of Doom" },
  653. { @"authors.0.email", @"fredflintstone@example.com" },
  654. { @"unknownAttributes.@count", @"0" },
  655. { @"unknownChildren.@count", @"0" },
  656. // entry paths
  657. { @"entries.0.content", @"Column Beta: clouds, Column Alpha: mars" },
  658. { @"entries.0.editLink.href", @"http://spreadsheets.google.com/feeds/RRHuSwAKiaEGw526z3DVYw/records/1/cn6ca" },
  659. { @"entries.0.fields.0.name", @"Column Beta" },
  660. { @"entries.0.fields.0.indexString", @"B" },
  661. { @"entries.0.fields.0.value", @"clouds" },
  662. { @"entries.0.fields.0.formula", @"3+something" },
  663. { @"entries.0.unknownAttributes.@count", @"0" },
  664. { @"entries.0.unknownChildren.@count", @"0" },
  665. { @"", @"" }, // end of feed
  666. { nil, nil } // end of test array
  667. };
  668. [self runTests:tests];
  669. }
  670. - (void)testAnalyticsFeeds {
  671. TestKeyPathValues tests[] =
  672. {
  673. //
  674. // Account feed
  675. //
  676. { @"GDataFeedAnalyticsAccount/2.0", @"Tests/FeedAnalyticsAccountTest1.xml" },
  677. // GDataFeedAnalyticsAccount paths
  678. { @"authors.0.name", @"Google Analytics" },
  679. { @"title", @"Profile list for fredflintstone@example.com" },
  680. { @"segments.0.name", @"All Visits" },
  681. { @"segments.0.analyticsID", @"gaid::-1" },
  682. { @"segments.0.definition", @"" },
  683. { @"segments.1.definition", @"ga:visitorType==New Visitor" },
  684. // GDataEntryAnalyticsAccount paths
  685. { @"entries.0.tableID", @"ga:7966084" },
  686. { @"entries.0.analyticsProperties.0.name", @"ga:accountId" },
  687. { @"entries.0.analyticsProperties.0.stringValue", @"8925159" },
  688. { @"entries.0.analyticsProperties.1.name", @"ga:accountName" },
  689. { @"entries.0.analyticsProperties.1.stringValue", @"example" },
  690. { @"entries.0.customVariables.0.index", @"3" },
  691. { @"entries.0.customVariables.0.name", @"User" },
  692. { @"entries.0.customVariables.0.scope", @"visitor" },
  693. { @"entries.0.goals.0.isActive", @"1" },
  694. { @"entries.0.goals.0.name", @"My Main Goal" },
  695. { @"entries.0.goals.0.number", @"1" },
  696. { @"entries.0.goals.0.value", @"1.100000023841858" },
  697. { @"entries.0.goals.0.destination.isCaseSensitive", @"0" },
  698. { @"entries.0.goals.0.destination.expression", @"/wiki/DocPage" },
  699. { @"entries.0.goals.0.destination.matchType", @"head" },
  700. { @"entries.0.goals.0.destination.isStep1Required", @"0" },
  701. { @"entries.0.goals.0.destination.steps.0.name", @"Wiki step" },
  702. { @"entries.0.goals.0.destination.steps.0.number", @"1" },
  703. { @"entries.0.goals.0.destination.steps.0.path", @"/wiki" },
  704. { @"entries.0.goals.0.engagement", nil },
  705. { @"", @"" }, // end of feed
  706. //
  707. // Data feed
  708. //
  709. { @"GDataFeedAnalyticsData/2.0", @"Tests/FeedAnalyticsDataTest1.xml" },
  710. // GDataFeedAnalyticsData paths
  711. { @"authors.0.name", @"Google Analytics" },
  712. { @"title", @"Google Analytics Data for Profile 7966084" },
  713. { @"startDateString", @"2009-05-18" },
  714. { @"endDateString", @"2009-05-20" },
  715. { @"aggregateGroup.metrics.0.confidenceInterval", @"0" },
  716. { @"aggregateGroup.metrics.0.name", @"ga:pageviews" },
  717. { @"aggregateGroup.metrics.0.type", kGDataMetricTypeInteger },
  718. { @"aggregateGroup.metrics.0.stringValue", @"12" },
  719. { @"aggregateGroup.metrics.0.doubleValue", @"12" },
  720. { @"dataSources.0.tableID", @"ga:7966084" },
  721. { @"dataSources.0.tableName", @"www.example.net" },
  722. { @"dataSources.0.analyticsProperties.0.name", @"ga:profileId" },
  723. { @"dataSources.0.analyticsProperties.0.stringValue", @"7966084" },
  724. { @"dataSources.0.analyticsPropertyWithNameAccountName.stringValue", @"example" },
  725. { @"segments.0.name", @"New Visitors" },
  726. { @"segments.0.analyticsID", @"gaid::-2" },
  727. { @"segments.0.definition", @"ga:visitorType==New Visitor" },
  728. // GDataEntryAnalyticsData paths
  729. { @"entries.0.title", @"ga:country=United States" },
  730. { @"entries.0.dimensions.0.name", @"ga:country" },
  731. { @"entries.0.dimensions.0.stringValue", @"United States" },
  732. { @"entries.0.dimensionWithNameCountry.stringValue", @"United States" },
  733. { @"entries.0.metrics.0.confidenceInterval", @"5.1" },
  734. { @"entries.0.metrics.0.name", @"ga:pageviews" },
  735. { @"entries.0.metrics.0.type", kGDataMetricTypeInteger },
  736. { @"entries.0.metrics.0.stringValue", @"37" },
  737. { @"entries.0.metrics.0.doubleValue", @"37" },
  738. { @"entries.0.metricWithNamePageviews.stringValue", @"37" },
  739. { @"", @"" }, // end of feed
  740. { nil, nil } // end of test array
  741. };
  742. [self runTests:tests];
  743. }
  744. - (void)testCodeSearchFeed {
  745. TestKeyPathValues tests[] =
  746. {
  747. //
  748. // Feed of a user's albums
  749. //
  750. { @"GDataFeedCodeSearch", @"Tests/FeedCodeSearchTest1.xml" },
  751. // GDataFeedCodeSearch paths
  752. { @"authors.0.name", @"Google Code Search" },
  753. { @"authors.0.URI", @"http://www.google.com/codesearch" },
  754. // GDataEntryCodeSearch paths
  755. { @"entries.0.package.name", @"http://ftp.funet.fi/pub/CPAN/src/perl-5.9.1.tar.gz" },
  756. { @"entries.0.package.URI", @"http://ftp.funet.fi/pub/CPAN/src/perl-5.9.1.tar.gz" },
  757. { @"entries.1.package.name", @"http://gentoo.osuosl.org/distfiles/Perl6-Pugs-6.2.12.tar.gz" },
  758. { @"entries.1.package.URI", @"http://gentoo.osuosl.org/distfiles/Perl6-Pugs-6.2.12.tar.gz" },
  759. { @"entries.1.file.name", @"Perl6-Pugs-6.2.12/t/subroutines/sub_named_params.t" },
  760. { @"entries.1.matches.0.lineNumberString", @"131" },
  761. { @"entries.1.matches.0.type", @"text/html" },
  762. { @"entries.1.matches.0", @"hasPrefix:<pre>my %fellowship" },
  763. { @"entries.1.matches.1.lineNumberString", @"132" },
  764. { @"entries.1.matches.1.type", @"text/html" },
  765. { @"entries.1.matches.1", @"hasPrefix:<pre>is(%fellowship&lt;hobbit&gt;" },
  766. { @"", @"" }, // end of feed
  767. { nil, nil } // end of test array
  768. };
  769. [self runTests:tests];
  770. }
  771. - (void)testPhotosFeeds {
  772. // TODO: test geoLocation once we have a good sample of it
  773. // Test a non-ASCII character and some html characters in a TextConstruct.
  774. // We'll allocate it dynamically since source code cannot contain non-ASCII.
  775. NSString *templateStr = @"Test %C Alb%Cm";
  776. NSString *photoAlbumName = [NSString stringWithFormat:templateStr,
  777. 0x262F, 0x00FC]; // yin yang, u with umlaut
  778. // Non-ascii photo description, includes the Wheel of Dharma
  779. NSString *photoDescriptionText = [NSString stringWithFormat:
  780. @"Caption for the car %C photo", 0x2638];
  781. TestKeyPathValues tests[] =
  782. {
  783. //
  784. // Feed of a user's albums
  785. //
  786. { @"GDataFeedPhotoUser", @"Tests/FeedPhotosUserAlbum1.xml" },
  787. // GDataFeedPhotosAlbum paths
  788. { @"username", @"TestdomainTestAccount" },
  789. { @"nickname", @"Greg" },
  790. { @"thumbnail", @"hasPrefix:http://lh3.google.com/image/TestdomainTestAccount" },
  791. { @"quotaLimit", @"1073741824" },
  792. { @"quotaUsed", @"108303" },
  793. { @"maxPhotosPerAlbum", @"500" },
  794. { @"categories.0.term", kGDataCategoryPhotosUser },
  795. { @"unknownAttributes.@count", @"0" },
  796. { @"unknownChildren.@count", @"0" },
  797. // GDataEntryPhotoAlbum paths
  798. { @"entries.0.categories.0.term", kGDataCategoryPhotosAlbum },
  799. { @"entries.0.mediaGroup.mediaTitle", photoAlbumName },
  800. { @"entries.0.mediaGroup.mediaDescription", @"Album description" },
  801. { @"entries.0.mediaGroup.mediaCredits.0", @"Greg" },
  802. { @"entries.0.mediaGroup.mediaContents.0.medium", @"image" },
  803. { @"entries.0.mediaGroup.mediaContents.0.type", @"image/jpeg" },
  804. { @"entries.0.mediaGroup.mediaContents.0.URLString", @"hasPrefix:http://lh5.google.com/image/TestdomainTestAccount" },
  805. { @"entries.0.mediaGroup.mediaThumbnails.0.height", @"160" },
  806. { @"entries.0.mediaGroup.mediaThumbnails.0.URLString", @"hasPrefix:http://lh5.google.com/image/TestdomainTestAccount" },
  807. { @"entries.0.GPhotoID", @"5067143575034336993" },
  808. { @"entries.0.access", @"public" },
  809. { @"entries.0.photosUsed", @"2" },
  810. { @"entries.0.commentCount", @"0" },
  811. { @"entries.0.bytesUsed", @"108303" },
  812. { @"entries.0.nickname", @"Greg" },
  813. { @"entries.0.photosLeft", @"498" },
  814. { @"entries.0.commentsEnabled", @"1" },
  815. { @"entries.0.location", @"Album Site" },
  816. { @"entries.0.timestamp.dateValue.timeIntervalSince1970", @"1179730800" },
  817. { @"entries.0.username", @"TestdomainTestAccount" },
  818. { @"entries.0.identifier", @"http://photos.googleapis.com/data/entry/api/user/TestdomainTestAccount/albumid/5067143575034336993" },
  819. { @"entries.0.title.type", @"text" },
  820. { @"entries.0.title", photoAlbumName },
  821. { @"entries.0.photoDescription", @"Album description" },
  822. { @"entries.0.rightsString", @"public" },
  823. { @"entries.0.unknownAttributes.@count", @"0" },
  824. { @"entries.0.unknownChildren.@count", @"0" },
  825. { @"", @"" }, // end of feed
  826. //
  827. // Feed of an album's photos
  828. //
  829. { @"GDataFeedPhotoAlbum/2.0", @"Tests/FeedPhotosAlbumPhoto1.xml" },
  830. // GDataFeedPhotoAlbum - feed paths
  831. { @"GPhotoID", @"5067143575034336993" },
  832. { @"access", @"public" },
  833. { @"photosUsed", @"2" },
  834. { @"commentCount", @"0" },
  835. { @"bytesUsed", @"108303" },
  836. { @"nickname", @"Greg" },
  837. { @"photosLeft", @"498" },
  838. { @"commentsEnabled", @"1" },
  839. { @"location", @"Album Site" },
  840. { @"timestamp.dateValue.timeIntervalSince1970", @"1179730800" },
  841. { @"username", @"TestdomainTestAccount" },
  842. { @"identifier", @"http://photos.googleapis.com/data/feed/api/user/test%40testdomain.net/albumid/5067143575034336993" },
  843. { @"title.type", @"text" },
  844. { @"title", photoAlbumName },
  845. { @"photoDescription", @"Album description" },
  846. { @"rights", @"public" },
  847. { @"categories.0.term", kGDataCategoryPhotosAlbum },
  848. { @"feedLink.href", @"contains:albumid/5067143575034336993" },
  849. { @"feedLink.rel", kGDataLinkRelFeed },
  850. { @"postLink.href", @"contains:albumid/5067143575034336993" },
  851. { @"postLink.rel", kGDataLinkRelPost },
  852. { @"alternateLink.href", @"contains:/TestAlbM" },
  853. { @"alternateLink.rel", @"alternate" },
  854. { @"selfLink.href", @"contains:test%40testdomain.net/albumid/5067143575034336993?start-index=1" },
  855. { @"selfLink.rel", @"self" },
  856. { @"firstEntry.GPhotoID", @"5067143579329304306" },
  857. { @"unknownAttributes.@count", @"0" },
  858. { @"unknownChildren.@count", @"0" },
  859. // GDataEntryPhoto - entry paths
  860. { @"entries.0.categories.0.term", kGDataCategoryPhotosPhoto },
  861. { @"entries.0.checksum", @"23512309abbs298" },
  862. { @"entries.0.GPhotoID", @"5067143579329304306" },
  863. { @"entries.0.albumID", @"5067143575034336993" },
  864. { @"entries.0.width", @"660" },
  865. { @"entries.0.height", @"433" },
  866. { @"entries.0.videoStatus", kGDataPhotoStatusReady },
  867. { @"entries.0.commentsEnabled", @"1" },
  868. { @"entries.0.size", @"87225" },
  869. { @"entries.0.commentCount", @"1" },
  870. { @"entries.0.timestamp.dateValue.timeIntervalSince1970", @"1179786301" },
  871. { @"entries.0.title", @"Car.jpg" },
  872. { @"entries.0.photoDescription", photoDescriptionText },
  873. { @"entries.0.content.sourceURI", @"http://lh3.google.com/image/TestdomainTestAccount/RlIcPQ_TFvI/AAAAAAAAAAs/3fvWtQLN3KI/Car.jpg" },
  874. { @"entries.0.content.type", @"image/jpeg" },
  875. { @"entries.0.mediaGroup.mediaTitle", @"Car.jpg" },
  876. { @"entries.0.mediaGroup.mediaDescription", photoDescriptionText },
  877. { @"entries.0.mediaGroup.mediaCredits.0", @"Greg" },
  878. { @"entries.0.mediaGroup.mediaContents.0.medium", @"image" },
  879. { @"entries.0.mediaGroup.mediaContents.0.type", @"image/jpeg" },
  880. { @"entries.0.mediaGroup.mediaContents.0.URLString", @"http://lh3.google.com/image/TestdomainTestAccount/RlIcPQ_TFvI/AAAAAAAAAAs/3fvWtQLN3KI/Car.jpg" },
  881. { @"entries.0.mediaGroup.mediaThumbnails.0.height", @"47" },
  882. { @"entries.0.mediaGroup.mediaThumbnails.0.width", @"72" },
  883. { @"entries.0.mediaGroup.mediaThumbnails.0.URLString", @"http://lh3.google.com/image/TestdomainTestAccount/RlIcPQ_TFvI/AAAAAAAAAAs/3fvWtQLN3KI/Car.jpg?imgmax=72" },
  884. { @"entries.0.mediaGroup.mediaKeywords", @"headlight, red car" },
  885. { @"entries.0.EXIFTags.tagDictionary.exposure", @"0.0080" },
  886. { @"entries.0.EXIFTags.tagDictionary.imageUniqueID", @"d8a9e8fd57a384d216f4b2a853d654fc" },
  887. { @"entries.0.editMediaLink.href", @"contains:5067143579329304306" },
  888. { @"entries.0.editMediaLink.type", @"image/jpeg" },
  889. { @"entries.0.alternateLink.href", @"contains:photo#5067143579329304306" },
  890. { @"entries.0.alternateLink.type", kGDataLinkTypeHTML },
  891. { @"entries.0.HTMLLink.href", @"contains:photo#5067143579329304306" },
  892. { @"entries.0.selfLink.href", @"contains:photoid/5067143579329304306" },
  893. { @"entries.0.selfLink.type", kGDataLinkTypeAtom },
  894. { @"entries.0.feedLink.href", @"contains:photoid/5067143579329304306" },
  895. { @"entries.0.feedLink.type", kGDataLinkTypeAtom },
  896. { @"entries.0.unknownAttributes.@count", @"0" },
  897. { @"entries.0.unknownChildren.@count", @"0" },
  898. { @"", @"" }, // end of feed
  899. //
  900. // Feed of a photo's comments
  901. //
  902. { @"GDataFeedPhoto/2.0", @"Tests/FeedPhotosPhotoComment1.xml" },
  903. // GDataFeedPhoto - feed paths
  904. { @"generator.URI", @"http://photos.google.com/" },
  905. { @"generator.name", @"Google Photos" },
  906. { @"generator.version", @"1.00" },
  907. { @"EXIFTags.tagDictionary.exposure", @"0.0080" },
  908. { @"categories.0.term", kGDataCategoryPhotosPhoto },
  909. { @"EXIFTags.tagDictionary.imageUniqueID", @"d8a9e8fd57a384d216f4b2a853d654fc" },
  910. { @"checksum", @"23512309abbs298" },
  911. { @"GPhotoID", @"5067143579329304306" },
  912. { @"albumID", @"5067143575034336993" },
  913. { @"width", @"660" },
  914. { @"height", @"433" },
  915. { @"commentsEnabled", @"1" },
  916. { @"size", @"87225" },
  917. { @"commentCount", @"1" },
  918. { @"timestamp.dateValue.timeIntervalSince1970", @"1179786301" },
  919. { @"title", @"Car.jpg" },
  920. { @"photoDescription", photoDescriptionText },
  921. { @"icon", @"http://lh3.google.com/image/TestdomainTestAccount/RlIcPQ_TFvI/AAAAAAAAAAs/3fvWtQLN3KI/Car.jpg?imgmax=288" },
  922. { @"unknownAttributes.@count", @"0" },
  923. { @"unknownChildren.@count", @"0" },
  924. // GDataEntryPhotoComment - entry paths
  925. { @"entries.0.photoID", @"5067143579329304306" },
  926. { @"entries.0.GPhotoID", @"5067146044640532244" },
  927. { @"entries.0.categories.0.term", kGDataCategoryPhotosComment },
  928. { @"entries.0.unknownAttributes.@count", @"0" },
  929. { @"entries.0.unknownChildren.@count", @"0" },
  930. { @"", @"" }, // end of feed
  931. //
  932. // Feed of a user's tags
  933. //
  934. // GDataFeedPhotoUser - feed paths
  935. { @"GDataFeedPhotoUser", @"Tests/FeedPhotosUserTag1.xml" },
  936. { @"username", @"TestdomainTestAccount" },
  937. { @"nickname", @"Greg" },
  938. { @"thumbnail", @"hasPrefix:http://lh3.google.com/image/TestdomainTestAccount" },
  939. { @"quotaLimit", @"1073741824" },
  940. { @"quotaUsed", @"108303" },
  941. { @"maxPhotosPerAlbum", @"500" },
  942. { @"categories.0.term", kGDataCategoryPhotosUser },
  943. { @"unknownAttributes.@count", @"0" },
  944. { @"unknownChildren.@count", @"0" },
  945. // GDataEntryPhotoTag - entry paths
  946. { @"entries.0.title", @"headlight" },
  947. { @"entries.0.photoDescription", @"headlight" },
  948. { @"entries.0.categories.0.term", kGDataCategoryPhotosTag },
  949. { @"entries.0.unknownAttributes.@count", @"0" },
  950. { @"entries.0.unknownChildren.@count", @"0" },
  951. { @"entries.1.title", @"red car" },
  952. { @"entries.1.photoDescription", @"red car" },
  953. { @"entries.1.categories.0.term", kGDataCategoryPhotosTag },
  954. { @"entries.1.unknownAttributes.@count", @"0" },
  955. { @"entries.1.unknownChildren.@count", @"0" },
  956. { @"", @"" }, // end of feed
  957. //
  958. // Feed of a user entry
  959. //
  960. // This is really a fake feed created by requesting just a single
  961. // user entry from the picasa server, using
  962. // GET http://photos.googleapis.com/data/entry/api/user/<username>
  963. //
  964. // GDataFeedPhotoUser - feed paths (none)
  965. // GDataEntryPhotoUser - entry paths
  966. { @"GDataFeedPhotoUser", @"Tests/FeedPhotosUserEntry1.xml" },
  967. { @"entries.0.nickname", @"Greg" },
  968. { @"entries.0.username", @"TestdomainTestAccount" },
  969. { @"entries.0.thumbnail", @"hasPrefix:http://lh3.google.com/image/TestdomainTestAccount/AAAAUbcFQeo" },
  970. { @"entries.0.identifier", @"http://photos.googleapis.com/data/entry/api/user/TestdomainTestAccount" },
  971. { @"entries.0.categories.0.term", kGDataCategoryPhotosUser },
  972. { @"entries.0.unknownAttributes.@count",