domunit.pp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. {**********************************************************************
  2. This file is part of the Free Component Library (FCL)
  3. fpcunit extensions required to run w3.org DOM test suites
  4. Copyright (c) 2008 by Sergei Gorelkin, [email protected]
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit domunit;
  12. {$mode objfpc}{$H+}
  13. interface
  14. uses
  15. Classes, SysUtils, DOM, XMLRead, contnrs, fpcunit;
  16. type
  17. { these two types are separated for the purpose of readability }
  18. _collection = array of DOMString; // unordered
  19. _list = _collection; // ordered
  20. TDOMTestBase = class(TTestCase)
  21. private
  22. procedure setImplAttr(const name: string; value: Boolean);
  23. function getImplAttr(const name: string): Boolean;
  24. protected
  25. // override for this one is generated by testgen for each descendant
  26. function GetTestFilesURI: string; virtual;
  27. protected
  28. FParser: TDOMParser;
  29. FAutoFree: TFPObjectList;
  30. procedure SetUp; override;
  31. procedure TearDown; override;
  32. procedure GC(obj: TObject);
  33. procedure Load(out doc: TDOMDocument; const uri: string);
  34. function getResourceURI(const res: WideString): WideString;
  35. function ContentTypeIs(const t: string): Boolean;
  36. function GetImplementation: TDOMImplementation;
  37. procedure CheckFeature(const name: string);
  38. procedure assertNull(const id: string; const ws: DOMString); overload;
  39. procedure assertEquals(const id: string; exp, act: TObject); overload;
  40. procedure assertEqualsList(const id: string; const exp: array of DOMString; const act: _list);
  41. procedure assertEqualsCollection(const id: string; const exp: array of DOMString; const act: _collection);
  42. procedure assertSame(const id: string; exp, act: TDOMNode);
  43. procedure assertSize(const id: string; size: Integer; obj: TDOMNodeList);
  44. procedure assertSize(const id: string; size: Integer; obj: TDOMNamedNodeMap);
  45. procedure assertInstanceOf(const id: string; obj: TObject; const typename: string);
  46. procedure assertURIEquals(const id: string;
  47. const scheme, path, host, file_, name, query, fragment: DOMString;
  48. IsAbsolute: Boolean; const Actual: DOMString);
  49. function bad_condition(const TagName: WideString): Boolean;
  50. property implementationAttribute[const name: string]: Boolean read getImplAttr write setImplAttr;
  51. end;
  52. procedure _append(var coll: _collection; const Value: DOMString);
  53. procedure _assign(out rslt: _collection; const value: array of DOMString);
  54. function IsSame(exp, act: TDOMNode): Boolean;
  55. implementation
  56. uses
  57. URIParser;
  58. procedure _append(var coll: _collection; const Value: DOMString);
  59. var
  60. L: Integer;
  61. begin
  62. L := Length(coll);
  63. SetLength(coll, L+1);
  64. coll[L] := Value;
  65. end;
  66. procedure _assign(out rslt: _collection; const value: array of DOMString);
  67. var
  68. I: Integer;
  69. begin
  70. SetLength(rslt, Length(value));
  71. for I := 0 to High(value) do
  72. rslt[I] := value[I];
  73. end;
  74. function IsSame(exp, act: TDOMNode): Boolean;
  75. begin
  76. Result := exp = act;
  77. end;
  78. procedure TDOMTestBase.SetUp;
  79. begin
  80. FParser := TDOMParser.Create;
  81. FParser.Options.PreserveWhitespace := True;
  82. FAutoFree := TFPObjectList.Create(True);
  83. end;
  84. procedure TDOMTestBase.TearDown;
  85. begin
  86. FreeAndNil(FAutoFree);
  87. FreeAndNil(FParser);
  88. end;
  89. procedure TDOMTestBase.GC(obj: TObject);
  90. begin
  91. FAutoFree.Add(obj);
  92. end;
  93. procedure TDOMTestBase.assertSame(const id: string; exp, act: TDOMNode);
  94. begin
  95. if exp <> act then
  96. begin
  97. assertNotNull(id, exp);
  98. assertNotNull(id, act);
  99. assertEquals(id, exp.nodeType, act.nodeType);
  100. assertEquals(id, exp.nodeValue, act.nodeValue);
  101. end;
  102. end;
  103. procedure TDOMTestBase.assertNull(const id: string; const ws: DOMString);
  104. begin
  105. if ws <> '' then
  106. Fail(id);
  107. end;
  108. procedure TDOMTestBase.assertEquals(const id: string; exp, act: TObject);
  109. begin
  110. inherited assertSame(id, exp, act);
  111. end;
  112. procedure TDOMTestBase.assertEqualsList(const id: string;
  113. const exp: array of DOMString; const act: _list);
  114. var
  115. I: Integer;
  116. begin
  117. AssertEquals(id, Length(exp), Length(act));
  118. // compare ordered
  119. for I := 0 to High(exp) do
  120. AssertEquals(id, exp[I], act[I]);
  121. end;
  122. procedure TDOMTestBase.assertEqualsCollection(const id: string; const exp: array of DOMString; const act: _collection);
  123. var
  124. I, J, matches: Integer;
  125. begin
  126. AssertEquals(id, Length(exp), Length(act));
  127. // compare unordered
  128. for I := 0 to High(exp) do
  129. begin
  130. matches := 0;
  131. for J := 0 to High(act) do
  132. if act[J] = exp[I] then
  133. Inc(matches);
  134. AssertTrue(id+': no match found for <'+exp[I]+'>', matches <> 0);
  135. AssertTrue(id+': multiple matches for <'+exp[I]+'>', matches = 1);
  136. end;
  137. end;
  138. procedure TDOMTestBase.assertSize(const id: string; size: Integer; obj: TDOMNodeList);
  139. begin
  140. AssertNotNull(id, obj);
  141. AssertEquals(id, size, obj.Length);
  142. end;
  143. procedure TDOMTestBase.assertSize(const id: string; size: Integer; obj: TDOMNamedNodeMap);
  144. begin
  145. AssertNotNull(id, obj);
  146. AssertEquals(id, size, obj.Length);
  147. end;
  148. function TDOMTestBase.getResourceURI(const res: WideString): WideString;
  149. var
  150. Base, Level: WideString;
  151. begin
  152. Base := GetTestFilesURI + 'files/';
  153. if not ResolveRelativeURI(Base, res+'.xml', Result) then
  154. Result := '';
  155. end;
  156. function TDOMTestBase.getImplAttr(const name: string): Boolean;
  157. begin
  158. if name = 'expandEntityReferences' then
  159. result := FParser.Options.ExpandEntities
  160. else if name = 'validating' then
  161. result := FParser.Options.Validate
  162. else if name = 'namespaceAware' then
  163. result := FParser.Options.Namespaces
  164. else if name = 'ignoringElementContentWhitespace' then
  165. result := not FParser.Options.PreserveWhitespace
  166. else
  167. begin
  168. Fail('Unknown implementation attribute: ''' + name + '''');
  169. result := False;
  170. end;
  171. end;
  172. procedure TDOMTestBase.setImplAttr(const name: string; value: Boolean);
  173. begin
  174. if name = 'validating' then
  175. FParser.Options.Validate := value
  176. else if name = 'expandEntityReferences' then
  177. FParser.Options.ExpandEntities := value
  178. else if name = 'coalescing' then
  179. // TODO: action unknown yet
  180. else if (name = 'signed') and value then
  181. Ignore('Setting implementation attribute ''signed'' to ''true'' is not supported')
  182. else if name = 'hasNullString' then
  183. // TODO: probably we cannot support this
  184. else if name = 'namespaceAware' then
  185. FParser.Options.Namespaces := value
  186. else if name = 'ignoringElementContentWhitespace' then
  187. FParser.Options.PreserveWhitespace := not value
  188. else
  189. Fail('Unknown implementation attribute: ''' + name + '''');
  190. end;
  191. procedure TDOMTestBase.Load(out doc: TDOMDocument; const uri: string);
  192. var
  193. t: TXMLDocument;
  194. begin
  195. doc := nil;
  196. FParser.ParseURI(getResourceURI(uri), t);
  197. doc := t;
  198. GC(t);
  199. end;
  200. procedure TDOMTestBase.assertInstanceOf(const id: string; obj: TObject; const typename: string);
  201. begin
  202. AssertTrue(id, obj.ClassNameIs(typename));
  203. end;
  204. // TODO: This is a very basic implementation, needs to be completed.
  205. procedure TDOMTestBase.assertURIEquals(const id: string; const scheme, path,
  206. host, file_, name, query, fragment: DOMString; IsAbsolute: Boolean;
  207. const Actual: DOMString);
  208. var
  209. URI: TURI;
  210. begin
  211. AssertTrue(id, Actual <> '');
  212. URI := ParseURI(utf8Encode(Actual));
  213. AssertEquals(id, URI.Document, utf8Encode(file_));
  214. end;
  215. function TDOMTestBase.bad_condition(const TagName: WideString): Boolean;
  216. begin
  217. Fail('Unsupported condition: '+ TagName);
  218. Result := False;
  219. end;
  220. function TDOMTestBase.ContentTypeIs(const t: string): Boolean;
  221. begin
  222. { For now, claim only xml as handled content.
  223. This may be extended with html and svg.
  224. }
  225. result := (t = 'text/xml');
  226. end;
  227. function TDOMTestBase.GetImplementation: TDOMImplementation;
  228. begin
  229. result := nil;
  230. end;
  231. procedure TDOMTestBase.CheckFeature(const name: string);
  232. begin
  233. // purpose/action is currently unknown
  234. end;
  235. function TDOMTestBase.GetTestFilesURI: string;
  236. begin
  237. result := '';
  238. end;
  239. end.