fpc/rtl/test/utclasses.pp
michael 1c3b41eb54 * Testsuite in punit format
git-svn-id: trunk@43425 -
2019-11-09 13:39:14 +00:00

1391 lines
35 KiB
ObjectPascal

unit utclasses;
{$mode objfpc}{$H+}
{$INTERFACES CORBA}
interface
uses
SysUtils, Classes, punit, utrtl;
implementation
Function TestBytesStream : Ansistring;
var
BS: TBytesStream;
MS: TMemoryStream;
B: TBytes;
begin
Result:='';
B := TBytes.Create(1, 2, 3);
BS := TBytesStream.Create(B);
// save it to regular memory stream
MS := TMemoryStream.Create;
try
BS.SaveToStream(MS);
finally
BS.Free;
end;
// now restore and compare
BS := TBytesStream.Create;
try
MS.Position := 0;
BS.LoadFromStream(MS);
B := BS.Bytes;
if not AssertTrue('Bytes differ',not (Length(B) < 3) or (B[0] <> 1) or (B[1] <> 2) or (B[2] <> 3)) then
Exit;
finally
BS.Free;
end;
MS.Free;
end;
type
tenum = (eena,eenb,eenc,eend,eene,eenf,eeng,eenh,eeni);
tset = set of tenum;
ttestclass1 = class(tcomponent)
private
fprop1: tset;
public
property prop1: tset read fprop1 write fprop1 stored true;
end;
ttestclass2 = class(ttestclass1)
published
property prop1;
end;
function TestStoredfalse : Ansistring;
var
testclass2,testclass3: ttestclass2;
stream1,stream2: tmemorystream;
str1: ansistring;
begin
Result:='';
str1:='';
testclass2:= ttestclass2.create(nil);
testclass2.prop1:= [eenb,eend,eene,eenh,eeni];
stream1:= tmemorystream.create;
try
stream1.writecomponent(testclass2);
stream2:= tmemorystream.create;
try
stream1.position:= 0;
objectbinarytotext(stream1,stream2);
stream1.position:= 0;
stream2.position:= 0;
setlength(str1,stream2.size);
move(stream2.memory^,str1[1],length(str1));
testclass3:=ttestclass2.create(nil);
stream1.readcomponent(testclass3);
if not AssertTrue('Property set',testclass3.prop1=[eenb,eend,eene,eenh,eeni]) then
Exit;
finally
stream2.free;
end;
finally
stream1.free;
end;
end;
type
TMyStringList = class(TStringList)
protected
ExchangeCount: LongInt;
procedure ExchangeItems(aLeft, aRight: Integer); override;
end;
procedure TMyStringList.ExchangeItems(aLeft, aRight: Integer);
begin
Inc(ExchangeCount);
inherited ExchangeItems(aLeft, aRight);
end;
procedure FillStringList(aList: TStrings);
begin
aList.Add('Beta');
aList.Add('Gamma');
aList.Add('Alpha');
aList.Add('Delta');
end;
type
TDummy = class
ExchangeCount: LongInt;
procedure Change(aSender: TObject);
end;
procedure TDummy.Change(aSender: TObject);
begin
Inc(ExchangeCount);
end;
Function Testtstringlistexchange : Ansistring;
var
sl: TStringList;
msl: TMyStringList;
dummy: TDummy;
begin
Result:='';
dummy := TDummy.Create;
try
sl := TStringList.Create;
try
FillStringList(sl);
sl.OnChange := @dummy.Change;
sl.Sort;
// only OnChange call in TStringList.Sort
If not AssertEquals(' OnChange call in TStringList.Sort',1, dummy.ExchangeCount) then
Exit;
finally
sl.Free;
end;
dummy.ExchangeCount := 0;
msl := TMyStringList.Create;
try
FillStringList(msl);
msl.OnChange := @dummy.Change;
msl.Sort;
// TMyStringList.ExchangeItems called 5 times
if Not AssertEquals('TMyStringList.ExhangeItems call count',3,msl.ExchangeCount) then
Exit;
// OnChange called once in Sort
if Not AssertEquals('Dummy.OnChange',1,dummy.ExchangeCount) then
Exit
finally
msl.Free;
end;
finally
dummy.Free;
end;
end;
type
TDummyVCLComObject = class(TInterfacedObject, IVCLComObject)
public
function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
function GetIDsOfNames(const IID: TGUID; Names: Pointer;
NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
function SafeCallException(ExceptObject: TObject;
ExceptAddr: Pointer): HResult; override;
procedure FreeOnRelease;
end;
var
c: TComponent;
v: IVCLComObject;
procedure DoCreateVCLComObject(Component: TComponent);
begin
Component.VCLComObject := Pointer(V);
end;
{ TDummyVCLComObject }
procedure TDummyVCLComObject.FreeOnRelease;
begin
end;
function TDummyVCLComObject.GetIDsOfNames(const IID: TGUID; Names: Pointer;
NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;stdcall;
begin
Result := E_NOTIMPL;
end;
function TDummyVCLComObject.GetTypeInfo(Index, LocaleID: Integer;
out TypeInfo): HResult;stdcall;
begin
Result := E_NOTIMPL;
end;
function TDummyVCLComObject.GetTypeInfoCount(out Count: Integer): HResult;stdcall;
begin
Result := E_NOTIMPL;
end;
function TDummyVCLComObject.Invoke(DispID: Integer; const IID: TGUID;
LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo,
ArgErr: Pointer): HResult;stdcall;
begin
Result := E_NOTIMPL;
end;
function TDummyVCLComObject.SafeCallException(ExceptObject: TObject;
ExceptAddr: Pointer): HResult;
begin
Result := E_UNEXPECTED;
end;
Function Testvclcomobject : Ansistring;
begin
Result:='';
v := TDummyVCLComObject.Create;
CreateVCLComObjectProc := @DoCreateVCLComObject;
c := TComponent.Create(nil);
if c.ComObject = nil then
Result:='No Comobject';
c.Free;
v := nil;
end;
Function TestLineBreak : String;
var
tmp: TStrings;
begin
tmp := TStringList.Create();
try
tmp.LineBreak := ',';
tmp.Text := 'a,b,c';
If tmp.Count<>3 then
exit('Count needs to be 3');
if tmp[0]<>'a' then
exit('First element a');
if tmp[1]<>'b' then
exit('Second element b');
if tmp[2]<>'c' then
exit('Third element c');
finally
tmp.Free;
end;
end;
Function TestAlwaysQuote : String;
Const
ResD = 'ItemOne,ItemTwo,ItemThree,''Item With Spaces''';
ResAQ = '''ItemOne'',''ItemTwo'',''ItemThree'',''Item With Spaces''';
Var
L : TStringList;
Begin
L:=TStringList.Create;
try
With L do
begin
Add('ItemOne');
Add('ItemTwo');
Add('ItemThree');
Add('Item With Spaces');
QuoteChar := '''';
if DelimitedText<>ResD then
Exit('Default fails');
AlwaysQuote := True;
if DelimitedText<>ResAQ then
Exit('AlwaysQuote fails');
end;
finally
L.Free;
end;
end;
Function TestGetNameValue : string;
var
l: tstringlist;
begin
l:= tstringlist.create;
try
l.add('bb');
l.MissingNameValueSeparatorAction:=mnvaValue;
If not (l.ValueFromIndex[0]='bb') then
Exit('mnvaValue value error');
If not (l.Names[0]='') then
Exit('mnvaValue name error');
l.MissingNameValueSeparatorAction:=mnvaName;
If not (l.ValueFromIndex[0]='') then
Exit('mnvaName value error');
If not (l.Names[0]='bb') then
Exit('mnvaName name error');
l.MissingNameValueSeparatorAction:=mnvaEmpty;
If not (l.ValueFromIndex[0]='') then
Exit('mnvaEmpty value error');
If not (l.Names[0]='') then
Exit('mnvaEmptyerror');
l.MissingNameValueSeparatorAction:=mnvaError;
try
Writeln(l.ValueFromIndex[0]);
Exit('mnvError value error');
except
// Ignore, expected
end;
finally
L.free;
end;
end;
type
TItem = class
public
Value: Integer;
constructor Create(aValue: Integer);
end;
TSortParameter = class
public
Desc: Boolean;
end;
{ TItem }
constructor TItem.Create(aValue: Integer);
begin
inherited Create;
Value := aValue;
end;
function Compare(Item1, Item2, Context: Pointer): Integer;
var
xItem1: TItem absolute Item1;
xItem2: TItem absolute Item2;
xParam: TSortParameter absolute Context;
begin
Result := xItem1.Value-xItem2.Value;
if xParam.Desc then
Result := -Result;
end;
Function TestSortContext : String;
var
L: TList;
I: Integer;
B: Boolean;
P: TSortParameter;
Procedure FreeItems;
var
I : integer;
begin
for I:=0 to L.Count-1 do
TObject(L[i]).Free;
end;
begin
L := TList.Create;
try
for I := 1 to 5 do
L.Add(TItem.Create(I));
P := TSortParameter.Create;
for B in Boolean do
begin
P.Desc := B;
L.Sort(@Compare, P);
if not B then
begin
For I:=1 to 5 do
If (TItem(L[i-1]).Value<>i) then
Exit(Format('ASC Error at %d',[I]));
end
else
For I:=1 to 5 do
If (TItem(L[i-1]).Value<>6-i) then
Exit(Format('DESC Error at %d',[I]));
end;
finally
P.Free;
FreeItems;
L.Free;
end;
end;
Function TestStringListReverse1: String;
Var
L,l2 : TStringList;
I : Integer;
begin
Result:='';
L2:=Nil;
L:=TStringList.Create;
try
L2:=TStringList.Create;
For I:=1 to 3 do
L.Add(IntToStr(I));
L.Reverse(L2);
For I:=0 to 2 do
if not AssertEquals('Item'+IntToStr(I),L[2-I],L2[I]) then exit;
finally
L.Free;
L2.Free;
end;
end;
Function TestStringListReverse2: String;
Var
L,l2 : TStrings;
I : Integer;
begin
Result:='';
L2:=Nil;
L:=TStringList.Create;
try
For I:=1 to 3 do
L.Add(IntToStr(I));
L2:=L.Reverse;
if not AssertEquals('Classname',L.ClassName,L2.ClassName) then exit;
For I:=0 to 2 do
if not AssertEquals('Item'+IntToStr(I),L[2-I],L2[I]) then exit;
finally
L.Free;
L2.Free;
end;
end;
Function TestStringsIndexOfStartAt : String;
Var
L : TStrings;
I : Integer;
begin
Result:='';
L:=TStringList.Create;
try
For I:=1 to 3 do
L.Add(IntToStr(I));
For I:=1 to 3 do
L.Add(IntToStr(I));
if not AssertEquals('Start at 0',2,L.IndexOf('3')) then exit;
if not AssertEquals('Start at 1',2,L.IndexOf('3',1)) then exit;
if not AssertEquals('Start at 2',2,L.IndexOf('3',2)) then exit;
if not AssertEquals('Start at 3',5,L.IndexOf('3',3)) then exit;
if not AssertEquals('Start at -1',5,L.IndexOf('3',-1)) then exit;
finally
L.Free;
end;
end;
Function TestStringsLastIndexOfStartAt : String;
Var
L : TStrings;
I : Integer;
begin
Result:='';
L:=TStringList.Create;
try
For I:=1 to 3 do
L.Add(IntToStr(I));
For I:=1 to 3 do
L.Add(IntToStr(I));
if not AssertEquals('Start at 0',5,L.LastIndexOf('3')) then exit;
if not AssertEquals('Start at 1',-1,L.LastIndexOf('3',1)) then exit;
if not AssertEquals('Start at 2',2,L.LastIndexOf('3',2)) then exit;
if not AssertEquals('Start at 3',2,L.LastIndexOf('3',3)) then exit;
if not AssertEquals('Start at -1',5,L.LastIndexOf('3',-1)) then exit;
if not AssertEquals('Start at -2',2,L.LastIndexOf('3',-2)) then exit;
finally
L.Free;
end;
end;
Function TestSlice: String;
Var
L,l2 : TStrings;
I : Integer;
begin
Result:='';
L:=TStringList.Create;
try
L2:=TStringList.Create;
For I:=1 to 3 do
L.Add(IntToStr(I));
L.Slice(1,l2);
if not AssertEquals('Item count',2,L2.Count) then exit;
if not AssertEquals('Item 0','2',L2[0]) then exit;
if not AssertEquals('Item 1','3',L2[1]) then exit;
finally
L2.Free;
L.Free;
end;
end;
Function TestSlice2 : String;
Var
L,l2 : TStrings;
I : Integer;
begin
Result:='';
L:=TStringList.Create;
try
For I:=1 to 3 do
L.Add(IntToStr(I));
L2:=L.Slice(1);
if not AssertEquals('Classname',L.ClassName,L2.ClassName) then exit;
if not AssertEquals('Item count',2,L2.Count) then exit;
if not AssertEquals('Item 0','2',L2[0]) then exit;
if not AssertEquals('Item 1','3',L2[1]) then exit;
finally
L2.Free;
L.Free;
end;
end;
Function TestFill : String;
Var
L : TStrings;
I : Integer;
begin
Result:='';
L:=TStringList.Create;
try
For I:=1 to 10 do
L.Add(IntToStr(I));
L.Fill(' ',3,7);
For I:=1 to 3 do
AssertEquals(IntToStr(I),IntToStr(I),L[i-1]);
For I:=3 to 7 do
AssertEquals(IntToStr(I),' ',L[i]);
For I:=9 to 10 do
AssertEquals(IntToStr(I),IntToStr(I),L[i-1]);
finally
L.Free;
end;
end;
Function TestFill2 : String;
Var
L : TStrings;
I : Integer;
begin
Result:='';
L:=TStringList.Create;
try
For I:=1 to 10 do
L.Add(IntToStr(I));
L.Fill(' ',3,-3);
For I:=1 to 3 do
AssertEquals(IntToStr(I),IntToStr(I),L[i-1]);
For I:=3 to 7 do
AssertEquals(IntToStr(I),' ',L[i]);
For I:=9 to 10 do
AssertEquals(IntToStr(I),IntToStr(I),L[i-1]);
finally
L.Free;
end;
end;
Type
TFilterStringList = Class(TStringList)
function DoFilter (const s: string): boolean;
end;
function TFilterStringList.DoFilter (const s: string): boolean;
begin
Result:=StrToInt(S)<6;
end;
Function TestFilter : String;
Var
L : TFilterStringList;
L2 : TStrings;
I : Integer;
begin
Result:='';
L:=TFilterStringList.Create;
try
For I:=1 to 10 do
L.Add(IntToStr(I));
L2:=L.Filter(@L.DoFilter);
if not AssertEquals('Classname',L.ClassName,L2.ClassName) then exit;
if not AssertEquals('Count',5,L2.Count) then exit;
For I:=1 to 5 do
AssertEquals(IntToStr(I),IntToStr(I),L2[i-1]);
finally
L.Free;
L2.Free;
end;
end;
Function TestFilter2 : String;
Var
L : TFilterStringList;
L2 : TStrings;
I : Integer;
begin
Result:='';
L2:=Nil;
L:=TFilterStringList.Create;
try
For I:=1 to 10 do
L.Add(IntToStr(I));
L2:=TStringList.Create;
L.Filter(@L.DoFilter,L2);
if not AssertEquals('Classname',L.ClassName,L2.ClassName) then exit;
if not AssertEquals('Count',5,L2.Count) then exit;
For I:=1 to 5 do
AssertEquals(IntToStr(I),IntToStr(I),L2[i-1]);
finally
L.Free;
L2.Free;
end;
end;
Type
TMapStringList = Class(TStringList)
function DoMap (const s: string): String;
end;
function TMapStringList.DoMap (const s: string): string;
begin
Result:=IntToStr(StrToInt(S)+10);
end;
Function TestMap : String;
Var
L : TMapStringList;
L2 : TStrings;
I : Integer;
begin
Result:='';
L:=TMapStringList.Create;
try
For I:=1 to 10 do
L.Add(IntToStr(I));
L2:=L.Map(@L.DoMap);
if not AssertEquals('Classname',L.ClassName,L2.ClassName) then exit;
if not AssertEquals('Count',10,L2.Count) then exit;
For I:=1 to 10 do
AssertEquals(IntToStr(I),IntToStr(I+10),L2[i-1]);
finally
L.Free;
L2.Free;
end;
end;
Function TestMap2 : String;
Var
L : TMapStringList;
L2 : TStrings;
I : Integer;
begin
Result:='';
L:=TMapStringList.Create;
try
For I:=1 to 10 do
L.Add(IntToStr(I));
L2:=TStringList.Create;
L.Map(@L.DoMap,L2);
if not AssertEquals('Count',10,L2.Count) then exit;
For I:=1 to 10 do
AssertEquals(IntToStr(I),IntToStr(I+10),L2[i-1]);
finally
L.Free;
L2.Free;
end;
end;
Type
TReduceStringList = Class(TStringList)
function DoReduce (const s1,s2: string): String;
end;
function TReduceStringList.DoReduce (const s1,s2: string): String;
begin
Result:=IntToStr(StrToInt(S1)+StrToInt(S2));
end;
Function TestReduce : String;
Var
L : TReduceStringList;
S : String;
I : Integer;
begin
Result:='';
L:=TReduceStringList.Create;
try
For I:=1 to 10 do
L.Add(IntToStr(I));
S:=L.Reduce(@L.DoReduce,'0');
If not AssertEquals('Correct','55',S) then exit;
finally
L.Free;
end;
end;
Function TestPop : String;
Var
L : TStringList;
I : Integer;
begin
Result:='';
L:=TStringList.Create;
try
For I:=1 to 10 do
L.Add(IntToStr(I));
For I:=10 downto 1 do
If not AssertEquals('Correct pop '+IntToStr(I),IntToStr(I),L.Pop) then exit;
If not AssertEquals('Correct pop at last','',L.Pop) then exit;
finally
L.Free;
end;
end;
Function TestShift : String;
Var
L : TStringList;
I : Integer;
begin
Result:='';
L:=TStringList.Create;
try
For I:=1 to 10 do
L.Add(IntToStr(I));
For I:=1 to 10 do
If not AssertEquals('Correct shift '+IntToStr(I),IntToStr(I),L.Shift) then exit;
If not AssertEquals('Correct shift at last','',L.shift) then exit;
finally
L.Free;
end;
end;
Type
TForeachStringList = Class(TStringList)
Public
res : String;
Procedure DoForeach (const s1: string);
end;
Procedure TForeachStringList.DoForEach(Const S1 : String);
begin
Res:=res+S1;
end;
Function TestForeach : String;
Var
L : TForeachStringList;
I : Integer;
begin
Result:='';
L:=TForeachStringList.Create;
try
For I:=1 to 10 do
L.Add(IntToStr(I));
L.Foreach(@L.DoForeach);
If not AssertEquals('Correct','12345678910',L.Res) then exit;
finally
L.Free;
end;
end;
Type
TForeachExStringList = Class(TStringList)
Public
res : String;
Procedure DoForeach (const s1: string; const aIndex : integer);
end;
Procedure TForeachExStringList.DoForEach(Const S1 : String; const aIndex : integer);
begin
Res:=res+S1+IntToStr(aIndex);
end;
Function TestForeachEx : String;
Var
L : TForeachExStringList;
I : Integer;
begin
Result:='';
L:=TForeachExStringList.Create;
try
For I:=1 to 10 do
L.Add(IntToStr(I));
L.Foreach(@L.DoForeach);
If not AssertEquals('Correct','102132435465768798109',L.Res) then exit;
finally
L.Free;
end;
end;
function CompareStringLists(Expected,TestSL : TStrings):string;
var
I : Integer;
begin
Result:='';
if Expected.Count<>TestSL.Count then
Exit('count mismatch: '+ inttostr(TestSL.Count)+' test strings; '+inttostr(Expected.Count)+' expected strings.');
for i:=0 to TestSL.Count-1 do
if (Expected.Count>i) and (TestSL[i]<>Expected[i]) then
Exit('Line '+IntToStr(i)+' mismatch, expected *'+Expected[i]+'*, got: *'+TestSL[i]);
end;
function ReadStrictDelimFalse:string;
// Test if input works with Delphi-compatible sdf output
// Strictdelimiter:=false (default) when processing the delimitedtext
//
// Mainly check if reading quotes is according to Delphi sdf specs and works.
// Based on del4.zip in bug 19610
const
// Matches del4.zip in bug 19610:
DelimText='normal_string;"quoted_string";"quoted;delimiter";"quoted and space";"""quoted_and_starting_quote";"""quoted, starting quote, and space";"quoted_with_tab'+#9+'character";"quoted_multi'+LineEnding+
'line"; UnquotedSpacesInfront;UnquotedSpacesAtTheEnd ; "Spaces before quoted string"';
var
TestSL: TStringList;
Expected: TStringList;
begin
//Expected values:
Expected:=TStringList.Create;
TestSL:=TStringList.Create;
try
Expected.Add('normal_string');
Expected.Add('quoted_string');
Expected.Add('quoted;delimiter');
Expected.Add('quoted and space');
Expected.Add('"quoted_and_starting_quote');
Expected.Add('"quoted, starting quote, and space');
Expected.Add('quoted_with_tab'+#9+'character');
Expected.Add('quoted_multi'+LineEnding+'line');
Expected.Add('UnquotedSpacesInfront');
Expected.Add('UnquotedSpacesAtTheEnd');
Expected.Add('Spaces before quoted string');
TestSL.Delimiter:=';'; //Match example in bug 19610, del4.zip
TestSL.StrictDelimiter:=false;
TestSL.DelimitedText:=DelimText;
Result:=CompareStringLists(Expected,TestSL);
finally
Expected.Free;
TestSL.Free;
end;
end;
function ReadStrictDelimTrue: string;
// Test if input works with Delphi-compatible sdf output
// Strictdelimiter:=true when processing the delimitedtext
//
// Mainly check if reading quotes is according to Delphi sdf specs and works.
// Based on del4.zip in bug 19610
const
// Matches del4.zip in bug 19610:
DelimText='normal_string;"quoted_string";"quoted;delimiter";"quoted and space";"""quoted_and_starting_quote";"""quoted, starting quote, and space";"quoted_with_tab'+#9+'character";"quoted_multi'+LineEnding+
'line"; UnquotedSpacesInfront;UnquotedSpacesAtTheEnd ; "Spaces before quoted string"';
var
TestSL: TStringList;
Expected: TStringList;
begin
result:='';
//Expected values:
Expected:=TStringList.Create;
TestSL:=TStringList.Create;
try
Expected.Add('normal_string');
Expected.Add('quoted_string');
Expected.Add('quoted;delimiter');
Expected.Add('quoted and space');
Expected.Add('"quoted_and_starting_quote');
Expected.Add('"quoted, starting quote, and space');
Expected.Add('quoted_with_tab'+#9+'character');
Expected.Add('quoted_multi'+LineEnding+'line');
Expected.Add(' UnquotedSpacesInfront');
Expected.Add('UnquotedSpacesAtTheEnd ');
Expected.Add(' "Spaces before quoted string"');
TestSL.Delimiter:=';'; //Match example in bug 19610, del4.zip
TestSL.StrictDelimiter:=true;
TestSL.DelimitedText:=DelimText;
Result:=CompareStringLists(Expected,TestSL);
finally
Expected.Free;
TestSL.Free;
end;
end;
function ReadStrictDelimFalseCornerCases: String;
// Test if input works with Delphi-compatible sdf output
// Strictdelimiter:=false (default) when processing the delimitedtext
//
// Has some corner cases that Delphi produces but are not evident from their
// documentation
// Based on del4.zip in bug 19610
const
// Matches del4.zip in bug 19610:
DelimText='"Spaces after quoted string" ;';
var
TestSL: TStringList;
Expected: TStringList;
begin
result:='';
//Expected values:
Expected:=TStringList.Create;
TestSL:=TStringList.Create;
try
Expected.Add('Spaces after quoted string');
Expected.Add('');
TestSL.Delimiter:=';'; //Match example in bug 19610, del4.zip
TestSL.StrictDelimiter:=false;
TestSL.DelimitedText:=DelimText;
Result:=CompareStringLists(Expected,TestSL);
finally
Expected.Free;
TestSL.Free;
end;
end;
function ReadStrictDelimTrueCornerCases: string;
// Test if input works with Delphi-compatible sdf output
// Strictdelimiter:=true when processing the delimitedtext
//
// Has some corner cases that Delphi produces but are not evident from their
// documentation
// Based on del4.zip in bug 19610
const
// Matches del4.zip in bug 19610:
DelimText='"Spaces after quoted string" ;';
var
TestSL: TStringList;
Expected: TStringList;
begin
Result:='';
//Expected values:
Expected:=TStringList.Create;
TestSL:=TStringList.Create;
try
// With delimiter true, we get 2 extra empty lines, also some spaces
Expected.Add('Spaces after quoted string');
Expected.Add(' ');
Expected.Add('');
TestSL.Delimiter:=';'; //Match example in bug 19610, del4.zip
TestSL.StrictDelimiter:=true;
TestSL.DelimitedText:=DelimText;
//Test:
Result:=CompareStringLists(Expected,TestSL);
finally
Expected.Free;
TestSL.Free;
end;
end;
function ReadStrictDelimTrueSafeQuote:string;
// Test if input works with sdf output that has always been quoted
// Delphi accepts this input even though it does not write it by default
// This is a more unambiguous format than unquoted
// Strictdelimiter:=true when processing the delimitedtext
//
const
DelimText='"normal_string";"""quoted_string""";"""quoted;delimiter""";"""quoted and space""";"""starting_quote";"string_with_tab'+#9+'character";"multi'+LineEnding+
'line";" SpacesInfront";"SpacesAtTheEnd ";" ""Spaces before quoted string"""';
var
TestSL: TStringList;
Expected: TStringList;
begin
result:='';
//Expected values:
Expected:=TStringList.Create;
TestSL:=TStringList.Create;
try
Expected.Add('normal_string');
Expected.Add('"quoted_string"');
Expected.Add('"quoted;delimiter"');
Expected.Add('"quoted and space"');
Expected.Add('"starting_quote');
Expected.Add('string_with_tab'+#9+'character');
Expected.Add('multi'+LineEnding+
'line');
Expected.Add(' SpacesInfront');
Expected.Add('SpacesAtTheEnd ');
Expected.Add(' "Spaces before quoted string"');
TestSL.Delimiter:=';'; //Match example in bug 19610, del4.zip
TestSL.StrictDelimiter:=true;
TestSL.DelimitedText:=DelimText;
Result:=CompareStringLists(Expected,TestSL);
finally
Expected.Free;
TestSL.Free;
end;
end;
function ReadStrictDelimFalseSafeQuote: string;
// Test if input works with sdf output that has always been quoted
// Delphi accepts this input even though it does not write it by default
// This is a more unambiguous format than unquoted
// Strictdelimiter:=false when processing the delimitedtext
//
const
DelimText='"normal_string";"""quoted_string""";"""quoted;delimiter""";"""quoted and space""";"""starting_quote";"string_with_tab'+#9+'character";"multi'+LineEnding+
'line";" SpacesInfront";"SpacesAtTheEnd ";" ""Spaces before quoted string"""';
var
TestSL: TStringList;
Expected: TStringList;
begin
Result:='';
//Expected values:
Expected:=TStringList.Create;
TestSL:=TStringList.Create;
try
Expected.Add('normal_string');
Expected.Add('"quoted_string"');
Expected.Add('"quoted;delimiter"');
Expected.Add('"quoted and space"');
Expected.Add('"starting_quote');
Expected.Add('string_with_tab'+#9+'character');
Expected.Add('multi'+LineEnding+'line');
Expected.Add(' SpacesInfront');
Expected.Add('SpacesAtTheEnd ');
Expected.Add(' "Spaces before quoted string"');
TestSL.Delimiter:=';'; //Match example in bug 19610, del4.zip
TestSL.StrictDelimiter:=false;
TestSL.DelimitedText:=DelimText;
Result:=CompareStringLists(Expected,TestSL);
finally
Expected.Free;
TestSL.Free;
end;
end;
function ReadCommatext: string;
// Test if input works with Delphi-compatible commatext
const
CommaText='normal_string,"quoted_string","quoted,delimiter","quoted and space","""quoted_and_starting_quote","""quoted, starting quote, and space","quoted_with_tab'+#9+'character","quoted_multi'+LineEnding+
'line"," UnquotedSpacesInfront","UnquotedSpacesAtTheEnd "," ""Spaces before quoted string"""';
var
TestSL: TStringList;
Expected: TStringList;
begin
result:='';
//Expected values:
Expected:=TStringList.Create;
TestSL:=TStringList.Create;
try
Expected.Add('normal_string');
Expected.Add('quoted_string');
Expected.Add('quoted,delimiter');
Expected.Add('quoted and space');
Expected.Add('"quoted_and_starting_quote');
Expected.Add('"quoted, starting quote, and space');
Expected.Add('quoted_with_tab'+#9+'character');
Expected.Add('quoted_multi'+LineEnding+
'line');
Expected.Add(' UnquotedSpacesInfront');
Expected.Add('UnquotedSpacesAtTheEnd ');
Expected.Add(' "Spaces before quoted string"');
TestSL.CommaText:=CommaText;
//Test:
Result:=CompareStringLists(Expected,TestSL);
finally
Expected.Free;
TestSL.Free;
end;
end;
Function CheckDelimited(TestSL : Tstrings; const Expected, ExpectedSafeQuote : string) : String;
begin
if (TestSL.DelimitedText<>Expected) and (TestSL.DelimitedText<>ExpectedSafeQuote) then
Exit('result: *'+TestSL.DelimitedText+'* while expected was: *'+Expected+'* - or, with safe quote output: *'+ExpectedSafeQuote+'*');
end;
function WriteStrictDelimFalse:string;
// Test if conversion stringlist=>delimitedtext gives the right data
// (right in this case: what Delphi outputs)
// Strictdelimiter:=false when processing the delimitedtext
const
Expected='normal_string;"""quoted_string""";"just;delimiter";"""quoted;delimiter""";"""quoted and space""";"""starting_quote";"single""quote";"""""quoted starting quote and space""";"with_tab'+#9+'character";"multi'+LineEnding+
'line";" UnquotedSpacesInfront";"UnquotedSpacesAtTheEnd ";" ""Spaces before quoted string"""';
//If we choose to output the "safely quoted" version, we need to test for it:
//Though this version is not the same output as Delphi, it leads to the
//same input if imported again (see ReadStrictDelimFalseSafeQuote for corresponding tests)
ExpectedSafeQuote='"normal_string";"""quoted_string""";"just;delimiter";"""quoted;delimiter""";"""quoted and space""";"""starting_quote";"single""quote";"""""quoted starting quote and space""";"with_tab'+#9+'character";"multi'+LineEnding+
'line";" UnquotedSpacesInfront";"UnquotedSpacesAtTheEnd ";" ""Spaces before quoted string"""';
var
TestSL: TStringList;
begin
Result:='';
TestSL:=TStringList.Create;
try
TestSL.Add('normal_string');
TestSL.Add('"quoted_string"');
TestSL.Add('just;delimiter');
TestSL.Add('"quoted;delimiter"');
TestSL.Add('"quoted and space"');
TestSL.Add('"starting_quote');
TestSL.Add('single"quote');
TestSL.Add('""quoted starting quote and space"');
TestSL.Add('with_tab'+#9+'character');
TestSL.Add('multi'+LineEnding+
'line');
TestSL.Add(' UnquotedSpacesInfront');
TestSL.Add('UnquotedSpacesAtTheEnd ');
TestSL.Add(' "Spaces before quoted string"');
TestSL.Delimiter:=';';
TestSL.StrictDelimiter:=false;
Result:=CheckDelimited(TestSL,Expected,ExpectedSafeQuote);
finally
TestSL.Free;
end;
end;
function WriteStrictDelimTrue:String;
// Test if conversion stringlist=>delimitedtext gives the right data
// (right in this case: what Delphi outputs)
// Strictdelimiter:=true when processing the delimitedtext
const
Expected='normal_string;"""quoted_string""";"just;delimiter";"""quoted;delimiter""";"""quoted and space""";"""starting_quote";"single""quote";"""""quoted starting quote and space""";with_tab'+#9+'character;multi'+LineEnding+
'line; UnquotedSpacesInfront;UnquotedSpacesAtTheEnd ;" ""Spaces before quoted string"""';
//If we choose to output the "safely quoted" version, we need to test for it:
//Though this version is not the same output as Delphi, it leads to the
//same input if imported again (see ReadStrictDelimTrueSafeQuote for corresponding tests)
ExpectedSafeQuote='"normal_string";"""quoted_string""";"just;delimiter";"""quoted;delimiter""";"""quoted and space""";"""starting_quote";"single""quote";"""""quoted starting quote and space""";"with_tab'+#9+'character";"multi'+LineEnding+
'line";" UnquotedSpacesInfront";"UnquotedSpacesAtTheEnd ";" ""Spaces before quoted string"""';
var
TestSL: TStringList;
begin
result:='';
TestSL:=TStringList.Create;
try
TestSL.Add('normal_string');
TestSL.Add('"quoted_string"');
TestSL.Add('just;delimiter');
TestSL.Add('"quoted;delimiter"');
TestSL.Add('"quoted and space"');
TestSL.Add('"starting_quote');
TestSL.Add('single"quote');
TestSL.Add('""quoted starting quote and space"');
TestSL.Add('with_tab'+#9+'character');
TestSL.Add('multi'+LineEnding+
'line');
TestSL.Add(' UnquotedSpacesInfront');
TestSL.Add('UnquotedSpacesAtTheEnd ');
TestSL.Add(' "Spaces before quoted string"');
TestSL.Delimiter:=';';
TestSL.StrictDelimiter:=true;
Result:=CheckDelimited(TestSL,Expected,ExpectedSafeQuote);
finally
TestSL.Free;
end;
end;
function ReadWriteStrictDelimFalse:String;
// Test if conversion stringlist=>delimitedtext=>stringlist gives identical data
// Strictdelimiter:=false (default) when processing the delimitedtext
var
TestSL: TStringList;
ResultSL: TStringList;
begin
result:='';
ResultSL:=TStringList.Create;
TestSL:=TStringList.Create;
try
TestSL.Add('normal_string');
TestSL.Add('"quoted_string"');
TestSL.Add('"quoted;delimiter"');
TestSL.Add('"quoted and space"');
TestSL.Add('"starting_quote');
TestSL.Add('""quoted, starting quote, and space"');
TestSL.Add('with_tab'+#9+'character');
TestSL.Add('multi'+LineEnding+
'line');
TestSL.Add(' UnquotedSpacesInfront');
TestSL.Add('UnquotedSpacesAtTheEnd ');
TestSL.Add(' "Spaces before quoted string"');
TestSL.Delimiter:=';';
TestSL.StrictDelimiter:=false;
ResultSL.Delimiter:=';';
ResultSL.StrictDelimiter:=false;
ResultSL.DelimitedText:=TestSL.DelimitedText;
Result:=CompareStringLists(ResultSL,TestSL);
finally
ResultSL.Free;
TestSL.Free;
end;
end;
function ReadWriteStrictDelimTrue:String;
// Test if conversion stringlist=>delimitedtext=>stringlist gives identical data
// Strictdelimiter:=true when processing the delimitedtext
var
TestSL: TStringList;
ResultSL: TStringList;
begin
result:='';
ResultSL:=TStringList.Create;
TestSL:=TStringList.Create;
try
TestSL.Add('normal_string');
TestSL.Add('"quoted_string"');
TestSL.Add('"quoted;delimiter"');
TestSL.Add('"quoted and space"');
TestSL.Add('"starting_quote');
TestSL.Add('""quoted, starting quote, and space"');
TestSL.Add('with_tab'+#9+'character');
TestSL.Add('multi'+LineEnding+
'line');
TestSL.Add(' UnquotedSpacesInfront');
TestSL.Add('UnquotedSpacesAtTheEnd ');
TestSL.Add(' "Spaces before quoted string"');
TestSL.Delimiter:=';';
TestSL.StrictDelimiter:=false;
ResultSL.Delimiter:=';';
ResultSL.StrictDelimiter:=true;
ResultSL.DelimitedText:=TestSL.DelimitedText;
//Test:
Result:=CompareStringLists(ResultSL,TestSL);
finally
ResultSL.Free;
TestSL.Free;
end;
end;
Function AddStrictDelimFalse : string;
var
TestSL: TStringList;
ResultSL: TStringList;
begin
result:='';
ResultSL:=TStringList.Create;
TestSL:=TStringList.Create;
try
TestSL.Add('a');
TestSL.Add('b');
TestSL.Add('c');
TestSL.StrictDelimiter:=false;
TestSL.AddDelimitedtext('"quoted and space"');
ResultSL.Add('a');
ResultSL.Add('b');
ResultSL.Add('c');
ResultSL.Add('quoted and space');
Result:=CompareStringLists(ResultSL,TestSL);
finally
ResultSL.Free;
TestSL.Free;
end;
end;
Procedure RegisterTests;
Var
P : Psuite;
begin
P:=EnsureSuite('Classes');
AddTest('Testvclcomobject',@Testvclcomobject,P);
AddTest('Testtstringlistexchange',@Testtstringlistexchange,P);
AddTest('TestStoredfalse',@TestStoredfalse,P);
AddTest('TestBytesStream',@TestBytesStream,P);
AddTest('TestLineBreak',@TestLineBreak,P);
AddTest('TestAlwaysQuote',@TestAlwaysQuote,P);
AddTest('TestGetNameValue',@TestGetNameValue,P);
AddTest('SortContext',@TestSortContext,P);
AddTest('TestStringlistReverse1',@TestStringListReverse1,P);
AddTest('TestStringlistReverse2',@TestStringListReverse2,P);
AddTest('TestStringsIndexOfStartAt',@TestStringsIndexOfStartAt,P);
AddTest('TestStringsLastIndexOfStartAt',@TestStringsLastIndexOfStartAt,P);
AddTest('TestSlice',@TestSlice,P);
AddTest('TestSlice2',@TestSlice2,P);
AddTest('TestFill',@TestFill,P);
AddTest('TestFill2',@TestFill2,P);
AddTest('TestFilter',@TestFilter,P);
AddTest('TestFilter2',@TestFilter,P);
AddTest('TestMap',@TestMap,P);
AddTest('TestMap2',@TestMap2,P);
AddTest('TestReduce',@TestReduce,P);
AddTest('TestPop',@TestPop,P);
AddTest('TestShift',@TestShift,P);
AddTest('TestForeach',@TestForeach,P);
AddTest('TestForeachEx',@TestForeachEx,P);
AddTest('ReadStrictDelimFalse',@ReadStrictDelimFalse,P);
AddTest('ReadStrictDelimTrue',@ReadStrictDelimTrue,P);
AddTest('ReadStrictDelimFalseCornerCases',@ReadStrictDelimFalseCornerCases,P);
AddTest('ReadStrictDelimTrueCornerCases',@ReadStrictDelimTrueCornerCases,P);
AddTest('ReadStrictDelimTrueSafeQuote',@ReadStrictDelimTrueSafeQuote,P);
AddTest('ReadStrictDelimFalseSafeQuote',@ReadStrictDelimFalseSafeQuote,P);
AddTest('ReadCommaText',@ReadCommaText,P);
AddTest('WriteStrictDelimFalse',@WriteStrictDelimFalse,P);
AddTest('WriteStrictDelimTrue',@WriteStrictDelimTrue,P);
AddTest('ReadWriteStrictDelimFalse',@ReadWriteStrictDelimFalse,P);
AddTest('ReadWriteStrictDelimTrue',@ReadWriteStrictDelimTrue,P);
AddTest('AddStrictDelimFalse',@AddStrictDelimFalse,P);
end;
initialization
RegisterTests;
end.