mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2026-01-18 20:56:33 +01:00
497 lines
12 KiB
ObjectPascal
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.
|
|
|