fpc/tests/test/units/fpcunit/tccollection.pp
2008-05-26 18:31:36 +00:00

497 lines
12 KiB
ObjectPascal

unit tccollection;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, fpcunit, testregistry;
type
{ TMyItem }
TMyItem = Class(TCollectionItem)
private
FNr: integer;
protected
// Expose
function GetOwner: TPersistent; override;
published
Property Nr : integer Read FNr Write FNr;
end;
{ TMyCollection }
TMyCollection = Class(TCollection)
Private
FOwner : TPersistent;
FUpdateCount : Integer;
FLastNotifyItem,
FLastUpdate : TCollectionItem;
FNotifyCount : Integer;
FLastNotify : TCollectionNotification;
Function GetOwner : TPersistent; override;
Public
procedure Update(Item: TCollectionItem); override;
procedure Notify(Item: TCollectionItem;Action: TCollectionNotification); override;
Procedure ResetUpdate;
Procedure ResetNotify;
property PropName;
end;
{ TTestTCollection }
TTestTCollection= class(TTestCase)
private
procedure AccessNegativeIndex;
procedure AccessTooBigIndex;
procedure DeleteNegativeIndex;
procedure DeleteTooBigIndex;
procedure MoveNegativeIndex;
procedure MoveTooBigIndex;
protected
FColl : TMyCollection;
Function MyItem(I : integer) : TMyItem;
procedure AddItems(ACount : Integer);
procedure SetUp; override;
procedure TearDown; override;
published
procedure TestCreate;
procedure TestAdd;
procedure TestItemCollection;
procedure TestAddTwo;
Procedure TestDelete;
procedure TestClear;
Procedure TestFreeItem;
Procedure TestMoveForward;
Procedure TestMoveBackward;
Procedure TestID;
Procedure TestItemOwner;
Procedure TestDisplayName;
procedure TestOwnerNamePath;
Procedure TestItemNamePath;
Procedure TestOwnerItemNamePath;
Procedure TestChangeCollection;
procedure TestAccesIndexOutOfBounds;
procedure TestDeleteIndexOutOfBounds;
procedure TestMoveIndexOutOfBounds;
Procedure TestUpdateAdd;
Procedure TestUpdateDelete;
Procedure TestUpdateDisplayName;
Procedure TestUpdateCount;
Procedure TestUpdateCountNested;
Procedure TestUpdateMove;
Procedure TestNotifyAdd;
Procedure TestNotifyDelete;
end;
implementation
procedure TTestTCollection.TestCreate;
begin
AssertEquals('Item count 0 at create',0,FColl.Count);
AssertEquals('ItemClass is TMyItem',TMyItem,FColl.ItemClass);
end;
procedure TTestTCollection.TestAdd;
begin
AddItems(1);
AssertEquals('Item count is 1 after add',1,FColl.Count);
AssertEquals('Item class is correct',FColl.ItemClass,FColl.Items[0].ClassType);
AssertEquals('Item index is 0',0,FColl.Items[0].Index);
AssertEquals('Item ID is 0',0,FColl.Items[0].Id);
end;
procedure TTestTCollection.TestItemCollection;
begin
AddItems(1);
If MyItem(0).Collection<>FColl then
Fail('Item''s Collection is not collection');
end;
procedure TTestTCollection.TestAddTwo;
Var
I: Integer;
begin
AddItems(3);
AssertEquals('Item count is 3 after add',3,FColl.Count);
For I:=0 to 2 do
begin
AssertEquals(Format('Item %d class is correct',[i]),FColl.ItemClass,FColl.Items[i].ClassType);
AssertEquals(Format('Item %d index is 0',[i]),i,FColl.Items[i].Index);
AssertEquals(Format('Item %d ID is 0',[i]),i,FColl.Items[i].Id);
AssertEquals(Format('Item %d ID is %d',[i,i+1]),i+1,MyItem(i).Nr);
end;
end;
procedure TTestTCollection.TestDelete;
begin
AddItems(3);
FColl.Delete(1);
AssertEquals('Item count after delete',2,FColl.Count);
AssertEquals('Item 0 ok after delete',1,MyItem(0).Nr);
AssertEquals('Item 1 ok after delete',3,MyItem(1).Nr);
end;
procedure TTestTCollection.TestClear;
begin
AddItems(3);
FColl.Clear;
AssertEquals('Item count after clear',0,FColl.Count);
end;
procedure TTestTCollection.TestFreeItem;
begin
AddItems(3);
MyItem(1).Free;
AssertEquals('Item count after free',2,FColl.Count);
AssertEquals('Item 0 ok after free',1,MyItem(0).Nr);
AssertEquals('Item 1 ok after free',3,MyItem(1).Nr);
end;
procedure TTestTCollection.TestMoveForward;
begin
AddItems(5);
MyItem(4).Index:=1;
AssertEquals('Item 0 ok after move',1,MyItem(0).Nr);
AssertEquals('Item 1 ok after move',5,MyItem(1).Nr);
AssertEquals('Item 2 ok after move',2,MyItem(2).Nr);
AssertEquals('Item 3 ok after move',3,MyItem(3).Nr);
AssertEquals('Item 4 ok after move',4,MyItem(4).Nr);
end;
procedure TTestTCollection.TestMoveBackward;
begin
AddItems(5);
MyItem(1).Index:=3;
AssertEquals('Item 0 ok after move',1,MyItem(0).Nr);
AssertEquals('Item 1 ok after move',3,MyItem(1).Nr);
AssertEquals('Item 2 ok after move',4,MyItem(2).Nr);
AssertEquals('Item 3 ok after move',2,MyItem(3).Nr);
AssertEquals('Item 4 ok after move',5,MyItem(4).Nr);
end;
procedure TTestTCollection.TestID;
Var
I : TMyItem;
begin
AddItems(5);
FColl.Delete(2);
FColl.Delete(2);
I:=TMyItem(FColl.Add);
AssertEquals('ID keeps counting up',5,I.Id)
end;
procedure TTestTCollection.TestItemOwner;
begin
AddItems(1);
If (MyItem(0).GetOwner<>FColl) then
Fail('Item owner is not collection');
end;
procedure TTestTCollection.TestDisplayName;
begin
AddItems(1);
AssertEquals('Displayname is classname','TMyItem',MyItem(0).DisplayName);
end;
procedure TTestTCollection.TestItemNamePath;
begin
AddItems(2);
AssertEquals('Item namepath is collection namepath+index',FColl.GetNamePath+'[0]',MyItem(0).GetNamePath);
AssertEquals('Item namepath is collection namepath+index',FColl.GetNamePath+'[1]',MyItem(1).GetNamePath);
end;
procedure TTestTCollection.TestOwnerItemNamePath;
Var
P : TPersistent;
begin
P:=TPersistent.Create;
try
TMyCollection(FColl).FOwner:=P;
AddItems(2);
TMyCollection(FColl).PropName:='Something';
AssertEquals('Item namepath is collection namepath+index','TPersistent.Something[0]',MyItem(0).GetNamePath);
finally
P.Free;
end;
end;
procedure TTestTCollection.TestOwnerNamePath;
Var
P : TPersistent;
begin
P:=TPersistent.Create;
try
TMyCollection(FColl).FOwner:=P;
AddItems(2);
TMyCollection(FColl).PropName:='Something';
AssertEquals('Namepath is collection namepath+index','TPersistent.Something',FColl.GetNamePath);
finally
P.Free;
end;
end;
procedure TTestTCollection.TestChangeCollection;
Var
FCol2 : TCollection;
I : TCollectionItem;
begin
AddItems(2);
FCol2:=TCollection.Create(TMyItem);
try
I:=FCol2.Add;
I.Collection:=FColl;
AssertEquals('Moved item, count of source is zero',0,FCol2.Count);
AssertEquals('Moved item, count of dest is 1',3,FColl.Count);
AssertEquals('Moved item, index is 2',2,I.Index);
If (FColl.Items[0].Collection<>FColl) then
Fail('Collection owner is not set correctly after move');
AssertEquals('Moved item, ID is 2',2,I.ID);
finally
FCol2.free;
end;
end;
procedure TTestTCollection.AccessNegativeIndex;
begin
FColl.Items[-1];
end;
procedure TTestTCollection.AccessTooBigIndex;
begin
FColl.Items[3];
end;
procedure TTestTCollection.TestAccesIndexOutOfBounds;
begin
AddItems(3);
AssertException('Access Negative Index',EListError,@AccessNegativeIndex);
AssertException('Access Index too big',EListError,@AccessTooBigIndex);
end;
procedure TTestTCollection.DeleteNegativeIndex;
begin
FColl.Delete(-1);
end;
procedure TTestTCollection.DeleteTooBigIndex;
begin
FColl.Delete(3);
end;
procedure TTestTCollection.TestDeleteIndexOutOfBounds;
begin
AddItems(3);
AssertException('Delete Negative Index',EListError,@DeleteNegativeIndex);
AssertException('Delete Index too big',EListError,@DeleteTooBigIndex);
end;
procedure TTestTCollection.MoveNegativeIndex;
begin
FColl.Items[1].Index:=-1;
end;
procedure TTestTCollection.MoveTooBigIndex;
begin
FColl.Items[1].Index:=3;
end;
procedure TTestTCollection.TestMoveIndexOutOfBounds;
begin
AddItems(3);
AssertException('Move Negative first index',EListError,@MoveNegativeIndex);
AssertException('Exchange Negative second index',EListError,@MoveTooBigIndex);
end;
procedure TTestTCollection.TestUpdateAdd;
begin
AddItems(1);
If (FColl.FLastUpdate<>Nil) then
Fail('update item found !');
AssertEquals('Update count is 1',1,FColl.FUpdateCount);
end;
procedure TTestTCollection.TestUpdateDelete;
begin
AddItems(1);
FColl.ResetUpdate;
FColl.Delete(0);
If (FColl.FLastUpdate<>Nil) then
Fail('update item found !');
AssertEquals('Update count is 1',1,FColl.FUpdateCount);
end;
procedure TTestTCollection.TestUpdateDisplayName;
begin
AddItems(1);
FColl.ResetUpdate;
MyItem(0).DisplayName:='Something';
AssertEquals('Display name notification. Update count is 1',1,FColl.FUpdateCount);
If (FColl.FLastUpdate<>MyItem(0)) then
Fail('No displayname update');
end;
procedure TTestTCollection.TestUpdateCount;
begin
FColl.BeginUpdate;
Try
AddItems(2);
AssertEquals('Beginupdate; adds. Update count is 0',0,FColl.FUpdateCount);
If (FColl.FLastUpdate<>Nil) then
Fail('Beginupdate; FlastUpdate not nil');
finally
FColl.EndUpdate;
end;
AssertEquals('Endupdate; adds. Update count is 1',1,FColl.FUpdateCount);
If (FColl.FLastUpdate<>Nil) then
Fail('Endupdate; FlastUpdate not nil');
end;
procedure TTestTCollection.TestUpdateCountNested;
begin
FColl.BeginUpdate;
Try
AddItems(2);
FColl.BeginUpdate;
Try
AddItems(2);
AssertEquals('Beginupdate 2; adds. Update count is 0',0,FColl.FUpdateCount);
If (FColl.FLastUpdate<>Nil) then
Fail('Beginupdate 2; FlastUpdate not nil');
finally
FColl.EndUpdate;
end;
AssertEquals('Endupdate 1; Update count is 0',0,FColl.FUpdateCount);
If (FColl.FLastUpdate<>Nil) then
Fail('EndUpdate 1; FlastUpdate not nil');
finally
FColl.EndUpdate;
end;
AssertEquals('Endupdate 2; adds. Update count is 1',1,FColl.FUpdateCount);
If (FColl.FLastUpdate<>Nil) then
Fail('Endupdate 2; FlastUpdate not nil');
end;
procedure TTestTCollection.TestUpdateMove;
begin
AddItems(5);
FColl.ResetUpdate;
MyItem(4).Index:=2;
AssertEquals('Moved item. Update count is 1',1,FColl.FUpdateCount);
If (FColl.FLastUpdate<>Nil) then
Fail('Moved item notification - not all items updated');
end;
procedure TTestTCollection.TestNotifyAdd;
begin
AddItems(1);
If (FColl.FLastNotifyItem<>MyItem(0)) then
Fail('No notify item found !');
AssertEquals('Notify count is 1',1,FColl.FNotifyCount);
AssertEquals('Notify action is cnAdded',Ord(cnAdded),Ord(FColl.FLastNotify));
end;
procedure TTestTCollection.TestNotifyDelete;
begin
AddItems(3);
FColl.ResetNotify;
FColl.Delete(1);
// cnDeleting/cnExtracing. Can't currently test for 2 events...
AssertEquals('Notify count is 2',2,FColl.FNotifyCount);
AssertEquals('Notify action is cnExtracted',Ord(cnExtracting),Ord(FColl.FLastNotify));
end;
function TTestTCollection.MyItem(I: integer): TMyItem;
begin
Result:=TMyItem(FColl.Items[i]);
end;
procedure TTestTCollection.AddItems(ACount: Integer);
Var
I : integer;
begin
For I:=1 to ACount do
TMyItem(FColl.Add).Nr:=I;
end;
procedure TTestTCollection.SetUp;
begin
FColl:=TMyCollection.Create(TMyItem);
end;
procedure TTestTCollection.TearDown;
begin
FreeAndNil(FColl);
end;
{ TMyItem }
function TMyItem.GetOwner: TPersistent;
begin
Result:=inherited GetOwner;
end;
{ TMyCollection }
function TMyCollection.GetOwner: TPersistent;
begin
Result:=FOwner;
If (Result=Nil) then
Result:=Inherited GetOwner;
end;
procedure TMyCollection.Update(Item: TCollectionItem);
begin
Inc(FUpdateCount);
FLastUpdate:=Item;
end;
procedure TMyCollection.Notify(Item: TCollectionItem;
Action: TCollectionNotification);
begin
Inc(FNotifyCount);
FLastNotify:=Action;
FLastNotifyItem:=Item;
end;
procedure TMyCollection.ResetUpdate;
begin
FUpdateCount:=0;
FLastUpdate:=Nil;
end;
procedure TMyCollection.ResetNotify;
begin
FNotifyCount:=0;
FLastNotifyItem:=Nil;
end;
initialization
RegisterTest(TTestTCollection);
end.