/core/externals/update-engine/externals/gdata-objectivec-client/Source/Tests/GDataXMLSupportTest.m

http://macfuse.googlecode.com/ · Objective C · 304 lines · 186 code · 63 blank · 55 comment · 6 complexity · d0130072d59f87ecb439b14904b9ddf5 MD5 · raw file

  1. /* Copyright (c) 2008 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. // GDataXMLSupportTest.m
  17. //
  18. #import <SenTestingKit/SenTestingKit.h>
  19. #import "GData/GData.h"
  20. #import "GDataXMLNode.h"
  21. @interface GDataXMLSupportTest : SenTestCase
  22. @end
  23. @implementation GDataXMLSupportTest
  24. - (void)runNodesAndNamespacesTestUsingShim:(BOOL)shouldUseShim {
  25. NSLog(@"Nodes and ns test %@ shim", shouldUseShim ? @"with" : @"without");
  26. // since we don't want the GDataDefines macros to replace NSXMLNode
  27. // with GDataXMLNode, we'll use strings to make the classes
  28. Class cXMLNode = NSClassFromString(shouldUseShim ?
  29. @"GDataXMLNode" : @"NSXMLNode");
  30. Class cXMLElement = NSClassFromString(shouldUseShim ?
  31. @"GDataXMLElement" : @"NSXMLElement");
  32. // create elements and attributes
  33. // create with URI and local name
  34. NSXMLElement *attr1 = [cXMLElement attributeWithName:@"foo"
  35. URI:kGDataNamespaceGData
  36. stringValue:@"baz"];
  37. NSXMLElement *child1 = [cXMLElement elementWithName:@"chyld"
  38. URI:kGDataNamespaceGData];
  39. [child1 setStringValue:@"fuzz"];
  40. // create with URI and prefix
  41. NSXMLElement *attr2 = [cXMLElement attributeWithName:@"openSearch:foo"
  42. stringValue:@"baz2"];
  43. NSXMLElement *child2 = [cXMLElement elementWithName:@"openSearch:chyld"];
  44. [child2 setStringValue:@"fuzz2"];
  45. // create with unqualified local name
  46. NSXMLElement *child3 = [cXMLElement elementWithName:@"chyld"];
  47. [child3 setStringValue:@"fuzz3"];
  48. NSXMLElement *child3temp = nil;
  49. if (shouldUseShim) {
  50. // create a child we'll later remove (GDataXMLElement API only)
  51. child3temp = [cXMLElement elementWithName:@"childTemp"];
  52. [child3temp setStringValue:@"scorch"];
  53. }
  54. // create with a missing namespace URI that we'll never actually add,
  55. // so we can test searches based on our faked use of {uri}: as
  56. // a prefix for the local name
  57. NSXMLElement *attr4 = [cXMLElement attributeWithName:@"zorgbot"
  58. URI:kGDataNamespaceBatch
  59. stringValue:@"gollyfum"];
  60. NSXMLElement *child4 = [cXMLElement elementWithName:@"zorgtree"
  61. URI:kGDataNamespaceBatch];
  62. [child4 setStringValue:@"gollyfoo"];
  63. // create an element with a local namespace not defined in the parent level
  64. NSString *lonerURI = @"http://loner.ns";
  65. NSXMLElement *child5 = [cXMLElement elementWithName:@"ln:loner"
  66. URI:lonerURI];
  67. NSXMLNode *ns5 = [cXMLNode namespaceWithName:@"ln"
  68. stringValue:lonerURI];
  69. [child5 addNamespace:ns5];
  70. // add these to a parent element, along with namespaces
  71. NSXMLElement *parent = [cXMLElement elementWithName:@"dad"];
  72. [parent setStringValue:@"buzz"];
  73. // atom is the default namespace
  74. NSXMLNode *nsAtom = [cXMLNode namespaceWithName:@""
  75. stringValue:kGDataNamespaceAtom];
  76. [parent addNamespace:nsAtom];
  77. NSXMLNode *nsGD = [cXMLNode namespaceWithName:@"gd"
  78. stringValue:kGDataNamespaceGData];
  79. [parent addNamespace:nsGD];
  80. NSXMLNode *nsOpenSearch = [cXMLNode namespaceWithName:@"openSearch"
  81. stringValue:kGDataNamespaceOpenSearch];
  82. [parent addNamespace:nsOpenSearch];
  83. [parent addChild:child1];
  84. [parent addAttribute:attr1];
  85. [parent addChild:child2];
  86. [parent addAttribute:attr2];
  87. [parent addChild:child3];
  88. if (shouldUseShim) {
  89. [parent addChild:child3temp];
  90. }
  91. [parent addChild:child4];
  92. [parent addAttribute:attr4];
  93. [parent addChild:child5];
  94. if (shouldUseShim) {
  95. // remove the temp child; we must obtain it from the tree, not use
  96. // the copy we added above
  97. NSArray *childrenToRemove = [parent elementsForName:@"childTemp"];
  98. STAssertEquals((int)[childrenToRemove count], 1, @"childTemp not found");
  99. GDataXMLNode *childToRemove = [childrenToRemove objectAtIndex:0];
  100. [(GDataXMLElement *)parent removeChild:childToRemove];
  101. childrenToRemove = [parent elementsForName:@"childTemp"];
  102. STAssertEquals((int)[childrenToRemove count], 0, @"childTemp still found");
  103. }
  104. // search for attr1 and child1 by qualified name, since they were
  105. // created by URI
  106. NSXMLNode *attr1Found = [parent attributeForName:@"gd:foo"];
  107. STAssertEqualObjects([attr1Found stringValue], @"baz", @"attribute gd:foo");
  108. NSArray *elements = [parent elementsForName:@"gd:chyld"];
  109. STAssertEquals((int)[elements count], 1, @"getting gd:chyld");
  110. NSXMLNode *child1Found = [elements objectAtIndex:0];
  111. STAssertEqualObjects([child1Found stringValue], @"fuzz", @"child gd:chyld");
  112. // search for attr2 and child2 by local name and URI, since they were
  113. // created by qualified names
  114. NSXMLNode *attr2Found = [parent attributeForLocalName:@"foo"
  115. URI:kGDataNamespaceOpenSearch];
  116. STAssertEqualObjects([attr2Found stringValue], @"baz2", @"attribute openSearch:foo");
  117. NSArray *elements2 = [parent elementsForLocalName:@"chyld"
  118. URI:kGDataNamespaceOpenSearch];
  119. STAssertEquals((int)[elements2 count], 1, @"getting openSearch:chyld");
  120. NSXMLNode *child2Found = [elements2 objectAtIndex:0];
  121. STAssertEqualObjects([child2Found stringValue], @"fuzz2", @"child openSearch:chyld");
  122. // search for child3 by local name
  123. NSArray *elements3 = [parent elementsForName:@"chyld"];
  124. STAssertEquals((int)[elements3 count], 1, @"getting chyld");
  125. NSXMLNode *child3Found = [elements3 objectAtIndex:0];
  126. STAssertEqualObjects([child3Found stringValue], @"fuzz3", @"child chyld");
  127. // search for child3 by URI
  128. NSArray *elements3a = [parent elementsForLocalName:@"chyld"
  129. URI:kGDataNamespaceAtom];
  130. STAssertEquals((int)[elements3a count], 1, @"getting chyld (URI");
  131. NSXMLNode *child3aFound = [elements3 objectAtIndex:0];
  132. STAssertEqualObjects([child3aFound stringValue], @"fuzz3", @"child chyld");
  133. // search for attr4 and child4 by local name and URI, since they were
  134. // created by URI and never bound to a prefix by a namespace declaration
  135. NSXMLNode *attr4Found = [parent attributeForLocalName:@"zorgbot"
  136. URI:kGDataNamespaceBatch];
  137. STAssertEqualObjects([attr4Found stringValue], @"gollyfum", @"in test batch zorgbot");
  138. NSArray *elements4 = [parent elementsForLocalName:@"zorgtree"
  139. URI:kGDataNamespaceBatch];
  140. STAssertEquals((int)[elements4 count], 1, @"getting batch zorgtree");
  141. NSXMLNode *child4Found = [elements4 objectAtIndex:0];
  142. STAssertEqualObjects([child4Found stringValue], @"gollyfoo", @"in test batch zorgtree");
  143. // search for child 5 by local name and URI, since it has a locally-defined
  144. // namespace
  145. NSArray *elements5 = [parent elementsForLocalName:@"loner"
  146. URI:lonerURI];
  147. STAssertEquals((int)[elements5 count], 1, @"getting loner");
  148. // test output
  149. NSString *expectedXML;
  150. if (shouldUseShim) {
  151. expectedXML = @"<dad xmlns=\"http://www.w3.org/2005/Atom\" "
  152. "xmlns:gd=\"http://schemas.google.com/g/2005\" "
  153. "xmlns:openSearch=\"http://a9.com/-/spec/opensearch/1.1/\" "
  154. "gd:foo=\"baz\" openSearch:foo=\"baz2\" "
  155. "{http://schemas.google.com/gdata/batch}:zorgbot=\"gollyfum\">"
  156. "buzz<gd:chyld>fuzz</gd:chyld><openSearch:chyld>fuzz2</openSearch:chyld>"
  157. "<chyld>fuzz3</chyld><{http://schemas.google.com/gdata/batch}:zorgtree>"
  158. "gollyfoo</{http://schemas.google.com/gdata/batch}:zorgtree>"
  159. "<ln:loner xmlns:ln=\"http://loner.ns\"/></dad>";
  160. } else {
  161. expectedXML = @"<dad xmlns=\"http://www.w3.org/2005/Atom\" "
  162. "xmlns:gd=\"http://schemas.google.com/g/2005\" "
  163. "xmlns:openSearch=\"http://a9.com/-/spec/opensearch/1.1/\" "
  164. "foo=\"baz\" openSearch:foo=\"baz2\" zorgbot=\"gollyfum\">"
  165. "buzz<chyld>fuzz</chyld><openSearch:chyld>fuzz2</openSearch:chyld>"
  166. "<chyld>fuzz3</chyld><zorgtree>gollyfoo</zorgtree>"
  167. "<ln:loner xmlns:ln=\"http://loner.ns\"></ln:loner></dad>";
  168. }
  169. NSString *actualXML = [parent XMLString];
  170. STAssertEqualObjects(actualXML, expectedXML, @"unexpected xml output");
  171. }
  172. - (void)testNodesAndNamespaces {
  173. [self runNodesAndNamespacesTestUsingShim:NO];
  174. [self runNodesAndNamespacesTestUsingShim:YES];
  175. }
  176. - (void)runXPathTestUsingShim:(BOOL)shouldUseShim {
  177. NSLog(@"XPath test %@ shim", shouldUseShim ? @"with" : @"without");
  178. // since we don't want the GDataDefines macros to replace NSXMLDocument
  179. // with GDataXMLDocument, we'll use strings to make the classes
  180. Class cXMLDocument = NSClassFromString(shouldUseShim ?
  181. @"GDataXMLDocument" : @"NSXMLDocument");
  182. // read in a big feed
  183. NSError *error = nil;
  184. NSStringEncoding encoding = 0;
  185. NSString *contactFeedXML = [NSString stringWithContentsOfFile:@"Tests/FeedContactTest1.xml"
  186. usedEncoding:&encoding
  187. error:&error];
  188. NSData *data = [contactFeedXML dataUsingEncoding:NSUTF8StringEncoding];
  189. NSXMLDocument *xmlDocument;
  190. xmlDocument = [[(NSXMLDocument *)[cXMLDocument alloc] initWithData:data
  191. options:0
  192. error:&error] autorelease];
  193. STAssertNotNil(xmlDocument, @"could not allocate feed from xml");
  194. STAssertNil(error, @"error allocating feed from xml");
  195. // I'd like to test namespace-uri here, too, but that fails in NSXML's XPath
  196. NSXMLElement *root = [xmlDocument rootElement];
  197. NSString *path = @"*[local-name()='category']";
  198. NSArray *nodes = [root nodesForXPath:path error:&error];
  199. STAssertEquals((int)[nodes count], 1, @"XPath count");
  200. STAssertNil(error, @"XPath error");
  201. if (shouldUseShim) {
  202. // NSXML's XPath doesn't seem to deal with URI's properly
  203. // find elements with the default namespace URI
  204. path = @"*[namespace-uri()='http://www.w3.org/2005/Atom']";
  205. nodes = [root nodesForXPath:path error:&error];
  206. STAssertEquals((int)[nodes count], 10, @"XPath count for default ns");
  207. STAssertNil(error, @"XPath error");
  208. // find elements with a non-default namespace URI
  209. path = @"*[namespace-uri()='http://a9.com/-/spec/opensearch/1.1/']";
  210. // find the opensearch nodes
  211. nodes = [root nodesForXPath:path error:&error];
  212. STAssertEquals((int)[nodes count], 3, @"XPath count for opensearch ns");
  213. STAssertNil(error, @"XPath error");
  214. // find nodes with the default atom namespace
  215. path = @"_def_ns:entry/_def_ns:link"; // four entry link nodes
  216. nodes = [root nodesForXPath:path error:&error];
  217. STAssertEquals((int)[nodes count], 4, @"XPath count for default ns nodes");
  218. STAssertNil(error, @"XPath error");
  219. // find nodes with an explicit atom namespace
  220. path = @"atom:entry/atom:link"; // four entry link nodes
  221. NSDictionary *nsDict = [NSDictionary dictionaryWithObject:kGDataNamespaceAtom
  222. forKey:kGDataNamespaceAtomPrefix];
  223. nodes = [(GDataXMLNode *)root nodesForXPath:path
  224. namespaces:nsDict
  225. error:&error];
  226. STAssertEquals((int)[nodes count], 4, @"XPath count for atom ns nodes");
  227. STAssertNil(error, @"XPath error");
  228. // test an illegal path string
  229. GDataXMLNode *emptyNode = [GDataXMLElement elementWithName:@"Abcde"];
  230. nodes = [emptyNode nodesForXPath:@""
  231. namespaces:nsDict
  232. error:&error];
  233. // libxml provides error code 1207 for this
  234. STAssertEquals([error code], (NSInteger)1207, @"error on invalid XPath: %@", error);
  235. }
  236. }
  237. - (void)testXPath {
  238. [self runXPathTestUsingShim:NO];
  239. [self runXPathTestUsingShim:YES];
  240. }
  241. @end