fpc/packages/fcl-xml/tests/domunit.pp
sergei 7cc9e5c18c * Provide distinct error messages.
git-svn-id: trunk@27121 -
2014-03-13 00:28:33 +00:00

340 lines
9.9 KiB
ObjectPascal

{**********************************************************************
This file is part of the Free Component Library (FCL)
fpcunit extensions required to run w3.org DOM test suites
Copyright (c) 2008 by Sergei Gorelkin, sergei_gorelkin@mail.ru
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
unit domunit;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, xmlutils, DOM, XMLRead, contnrs, fpcunit;
type
{ these two types are separated for the purpose of readability }
_collection = array of DOMString; // unordered
_list = _collection; // ordered
TDOMTestBase = class(TTestCase)
private
procedure setImplAttr(const name: string; value: Boolean);
function getImplAttr(const name: string): Boolean;
protected
// override for this one is generated by testgen for each descendant
function GetTestFilesURI: string; virtual;
protected
FParser: TDOMParser;
FAutoFree: TObjectList;
procedure SetUp; override;
procedure TearDown; override;
procedure GC(obj: TObject);
procedure Load(out doc; const uri: string);
procedure LoadStringData(out Doc; const data: string);
function getResourceURI(const res: XMLString): XMLString;
function ContentTypeIs(const t: string): Boolean;
function GetImplementation: TDOMImplementation;
procedure CheckFeature(const name: string);
procedure assertNull(const id: string; const ws: DOMString); overload;
procedure assertEquals(const id: string; exp, act: TObject); overload;
procedure assertEqualsList(const id: string; const exp: array of DOMString; const act: _list);
procedure assertEqualsCollection(const id: string; const exp: array of DOMString; const act: _collection);
procedure assertEqualsW(const id: string; const exp, act: DOMString);
procedure assertEqualsNoCase(const id: string; const exp, act: DOMString);
procedure assertSame(const id: string; exp, act: TDOMNode);
procedure assertSize(const id: string; size: Integer; obj: TDOMNodeList);
procedure assertSize(const id: string; size: Integer; obj: TDOMNamedNodeMap);
procedure assertInstanceOf(const id: string; obj: TObject; const typename: string);
procedure assertURIEquals(const id: string;
scheme, path, host, file_, name, query, fragment: PChar;
IsAbsolute: Boolean; const Actual: DOMString);
function bad_condition(const TagName: XMLString): Boolean;
property implementationAttribute[const name: string]: Boolean read getImplAttr write setImplAttr;
end;
procedure _append(var coll: _collection; const Value: DOMString);
procedure _assign(out rslt: _collection; const value: array of DOMString);
function IsSame(exp, act: TDOMNode): Boolean;
implementation
uses
URIParser;
procedure _append(var coll: _collection; const Value: DOMString);
var
L: Integer;
begin
L := Length(coll);
SetLength(coll, L+1);
coll[L] := Value;
end;
procedure _assign(out rslt: _collection; const value: array of DOMString);
var
I: Integer;
begin
SetLength(rslt, Length(value));
for I := 0 to High(value) do
rslt[I] := value[I];
end;
function IsSame(exp, act: TDOMNode): Boolean;
begin
Result := exp = act;
end;
procedure TDOMTestBase.SetUp;
begin
FParser := TDOMParser.Create;
FParser.Options.PreserveWhitespace := True;
//FParser.Options.ExpandEntities := True;
FAutoFree := TObjectList.Create(True);
end;
procedure TDOMTestBase.TearDown;
begin
FreeAndNil(FAutoFree);
FreeAndNil(FParser);
end;
procedure TDOMTestBase.GC(obj: TObject);
begin
FAutoFree.Add(obj);
end;
procedure TDOMTestBase.assertSame(const id: string; exp, act: TDOMNode);
begin
if exp <> act then
begin
assertNotNull(id, exp);
assertNotNull(id, act);
assertEquals(id, exp.nodeType, act.nodeType);
assertEqualsW(id, exp.nodeValue, act.nodeValue);
end;
end;
procedure TDOMTestBase.assertNull(const id: string; const ws: DOMString);
begin
if ws <> '' then
Fail(id);
end;
procedure TDOMTestBase.assertEquals(const id: string; exp, act: TObject);
begin
inherited assertSame(id, exp, act);
end;
procedure TDOMTestBase.assertEqualsList(const id: string;
const exp: array of DOMString; const act: _list);
var
I: Integer;
begin
AssertEquals(id+'(length)', Length(exp), Length(act));
// compare ordered
for I := 0 to High(exp) do
AssertEqualsW(id+'['+IntToStr(I)+']', exp[I], act[I]);
end;
procedure TDOMTestBase.assertEqualsCollection(const id: string; const exp: array of DOMString; const act: _collection);
var
I, J, matches: Integer;
begin
AssertEquals(id, Length(exp), Length(act));
// compare unordered
for I := 0 to High(exp) do
begin
matches := 0;
for J := 0 to High(act) do
if act[J] = exp[I] then
Inc(matches);
AssertTrue(id+': no match found for <'+exp[I]+'>', matches <> 0);
AssertTrue(id+': multiple matches for <'+exp[I]+'>', matches = 1);
end;
end;
procedure TDOMTestBase.assertEqualsW(const id: string; const exp, act: DOMString);
begin
AssertTrue(id + ComparisonMsg(exp, act), exp = act);
end;
procedure TDOMTestBase.assertEqualsNoCase(const id: string; const exp, act: DOMString);
begin
// TODO: could write custom comparison because range is limited to ASCII
AssertTrue(id + ComparisonMsg(exp, act), WideSameText(exp, act));
end;
procedure TDOMTestBase.assertSize(const id: string; size: Integer; obj: TDOMNodeList);
begin
AssertNotNull(id, obj);
AssertEquals(id, size, obj.Length);
end;
procedure TDOMTestBase.assertSize(const id: string; size: Integer; obj: TDOMNamedNodeMap);
begin
AssertNotNull(id, obj);
AssertEquals(id, size, obj.Length);
end;
function TDOMTestBase.getResourceURI(const res: XMLString): XMLString;
var
Base, Base2: XMLString;
function CheckFile(const uri: XMLString; out name: XMLString): Boolean;
var
filename: string;
begin
Result := ResolveRelativeURI(uri + 'files/', res + '.xml', name) and
URIToFilename(name, filename) and
FileExists(filename);
end;
begin
Base := GetTestFilesURI;
if Pos(XMLString('level2/html'), Base) <> 0 then
begin
// This is needed to run HTML testsuite off the CVS snapshot.
// Web version simply uses all level1 files copied to level2.
if ResolveRelativeURI(Base, '../../level1/html/', Base2) and
CheckFile(Base2, Result) then
Exit;
end;
CheckFile(Base, Result);
end;
function TDOMTestBase.getImplAttr(const name: string): Boolean;
begin
if name = 'expandEntityReferences' then
result := FParser.Options.ExpandEntities
else if name = 'validating' then
result := FParser.Options.Validate
else if name = 'namespaceAware' then
result := FParser.Options.Namespaces
else if name = 'ignoringElementContentWhitespace' then
result := not FParser.Options.PreserveWhitespace
else
begin
Fail('Unknown implementation attribute: ''' + name + '''');
result := False;
end;
end;
procedure TDOMTestBase.setImplAttr(const name: string; value: Boolean);
begin
if name = 'validating' then
FParser.Options.Validate := value
else if name = 'expandEntityReferences' then
FParser.Options.ExpandEntities := value
else if name = 'coalescing' then
// TODO: action unknown yet
else if (name = 'signed') and value then
Ignore('Setting implementation attribute ''signed'' to ''true'' is not supported')
else if name = 'hasNullString' then
// TODO: probably we cannot support this
else if name = 'namespaceAware' then
FParser.Options.Namespaces := value
else if name = 'ignoringElementContentWhitespace' then
FParser.Options.PreserveWhitespace := not value
else
Fail('Unknown implementation attribute: ''' + name + '''');
end;
procedure TDOMTestBase.Load(out doc; const uri: string);
var
t: TXMLDocument;
begin
TObject(doc) := nil;
FParser.ParseURI(getResourceURI(uri), t);
TObject(doc) := t;
GC(t);
end;
procedure TDOMTestBase.assertInstanceOf(const id: string; obj: TObject; const typename: string);
begin
AssertTrue(id, obj.ClassNameIs(typename));
end;
{ expected args already UTF-8 encoded }
procedure TDOMTestBase.assertURIEquals(const id: string; scheme, path,
host, file_, name, query, fragment: PChar; IsAbsolute: Boolean;
const Actual: DOMString);
var
URI: TURI;
begin
AssertTrue(id+'#0', Actual <> '');
URI := ParseURI(utf8Encode(Actual));
if fragment <> nil then
AssertEquals(id+'#1', string(fragment), URI.Bookmark);
if query <> nil then
AssertEquals(id+'#2', string(query), URI.Params);
if scheme <> nil then
AssertEquals(id+'#3', string(scheme), URI.Protocol);
if host <> nil then
begin
AssertTrue(id+'#4', URI.HasAuthority);
AssertEquals(id+'#5', string(host), URI.Host);
end;
if path <> nil then
AssertEquals(id+'#6', string(path), '//' + Uri.Host + URI.Path + URI.Document);
if file_ <> nil then
AssertEquals(id+'#7', string(file_), URI.Document);
if name <> nil then
AssertEquals(id+'#8', string(name), ChangeFileExt(URI.Document, ''));
end;
function TDOMTestBase.bad_condition(const TagName: XMLString): Boolean;
begin
Fail('Unsupported condition: '+ AnsiString(TagName));
Result := False;
end;
function TDOMTestBase.ContentTypeIs(const t: string): Boolean;
begin
{ For now, claim only xml as handled content.
This may be extended with html and svg.
}
result := (t = 'text/xml');
end;
function TDOMTestBase.GetImplementation: TDOMImplementation;
begin
result := nil;
end;
procedure TDOMTestBase.CheckFeature(const name: string);
begin
// purpose/action is currently unknown
end;
function TDOMTestBase.GetTestFilesURI: string;
begin
result := '';
end;
procedure TDOMTestBase.LoadStringData(out Doc; const data: string);
var
src: TXMLInputSource;
begin
src := TXMLInputSource.Create(data);
try
FParser.Parse(src, TXMLDocument(Doc));
GC(TObject(Doc));
finally
src.Free;
end;
end;
end.