1
0
mirror of synced 2024-12-22 09:13:07 +01:00

Added: unit tests for hashes

Added: Clear method
Fixed: bug in key storage and comparison
This commit is contained in:
Mark van Renswoude 2005-07-01 11:43:59 +00:00
parent 6628708958
commit 6429b349c3
5 changed files with 276 additions and 52 deletions

View File

@ -1,4 +1,4 @@
unit UBits; unit BitsTest;
interface interface
uses uses
@ -20,7 +20,7 @@ uses
X2UtBits; X2UtBits;
const const
BitsTest = [bit1, bit2, bit4, bit7]; Bits = [bit1, bit2, bit4, bit7];
BitsValue = 150; BitsValue = 150;
BitsString = '10010110'; BitsString = '10010110';
@ -33,7 +33,7 @@ var
begin begin
bValue := BitsValue; bValue := BitsValue;
Check(eBits = BitsTest, 'Bits do not match the value!'); Check(eBits = Bits, 'Bits do not match the value!');
end; end;
procedure TBitsTest.testSet; procedure TBitsTest.testSet;
@ -42,7 +42,7 @@ var
eBits: T8Bits absolute bValue; eBits: T8Bits absolute bValue;
begin begin
eBits := BitsTest; eBits := Bits;
Check(bValue = BitsValue, 'Value does not match the bits!'); Check(bValue = BitsValue, 'Value does not match the bits!');
end; end;
@ -67,7 +67,7 @@ var
sValue: String; sValue: String;
begin begin
eBits := BitsTest; eBits := Bits;
sValue := BitsToString(eBits, bs8); sValue := BitsToString(eBits, bs8);
Check(sValue = BitsString, 'Bits do not match the string!'); Check(sValue = BitsString, 'Bits do not match the string!');
@ -82,7 +82,7 @@ begin
sValue := BitsString; sValue := BitsString;
eBits := StringToBits(sValue); eBits := StringToBits(sValue);
Check(eBits = BitsTest, 'String does not match the bits!'); Check(eBits = Bits, 'String does not match the bits!');
end; end;

View File

@ -0,0 +1,217 @@
unit HashesTest;
interface
uses
TestFramework,
X2UtHashes;
type
THashesTest = class(TTestCase)
private
FHash: TX2CustomHash;
protected
procedure TearDown(); override;
procedure FillTestItems(); virtual; abstract;
published
procedure testSet(); virtual; abstract;
procedure testGet(); virtual; abstract;
procedure testClear();
procedure testDelete(); virtual; abstract;
procedure testIterate(); virtual; abstract;
end;
// Two test cases involving all value managers.
// This should be sufficient for a realistic scenario.
THashesSITest = class(THashesTest)
private
function GetHash(): TX2SIHash;
property Hash: TX2SIHash read GetHash;
protected
procedure SetUp(); override;
procedure FillTestItems(); override;
published
procedure testSet(); override;
procedure testGet(); override;
procedure testDelete(); override;
procedure testIterate(); override;
end;
THashesPOTest = class(THashesTest)
private
function GetHash(): TX2POHash;
property Hash: TX2POHash read GetHash;
protected
procedure SetUp(); override;
procedure FillTestItems(); override;
published
procedure testSet(); override;
procedure testGet(); override;
procedure testDelete(); override;
procedure testIterate(); override;
end;
implementation
uses
SysUtils;
type
TObject0 = class(TObject);
TObject1 = class(TObject);
TObject2 = class(TObject);
{ THashesTest }
procedure THashesTest.TearDown;
begin
FreeAndNil(FHash);
inherited;
end;
procedure THashesTest.testClear;
begin
FillTestItems();
FHash.Clear();
CheckEquals(0, FHash.Count);
end;
{ THashesSITest }
procedure THashesSITest.SetUp;
begin
inherited;
FHash := TX2SIHash.Create();
end;
procedure THashesSITest.FillTestItems;
begin
Hash['Key1'] := 1;
Hash['Key2'] := 2;
Hash['Key3'] := 3;
end;
procedure THashesSITest.testSet;
begin
FillTestItems();
CheckEquals(3, Hash.Count);
end;
procedure THashesSITest.testGet;
begin
FillTestItems();
CheckEquals(1, Hash['Key1']);
CheckEquals(2, Hash['Key2']);
CheckEquals(3, Hash['Key3']);
end;
procedure THashesSITest.testDelete;
begin
FillTestItems();
Hash.Delete('Key2');
CheckEquals(2, Hash.Count);
CheckTrue(Hash.Exists('Key1'), 'Key1 does not exist!');
CheckFalse(Hash.Exists('Key2'), 'Key2 still exists!');
CheckTrue(Hash.Exists('Key3'), 'Key3 does not exist!');
end;
procedure THashesSITest.testIterate;
var
aPresent: array[1..3] of Boolean;
begin
FillTestItems();
FillChar(aPresent, SizeOf(aPresent), #0);
Hash.First();
while Hash.Next() do
if ((Hash.CurrentKey = 'Key1') and (Hash.CurrentValue = 1)) or
((Hash.CurrentKey = 'Key2') and (Hash.CurrentValue = 2)) or
((Hash.CurrentKey = 'Key3') and (Hash.CurrentValue = 3)) then
aPresent[Hash.CurrentValue] := True;
CheckTrue(aPresent[1], 'Key1 was not in the iteration!');
CheckTrue(aPresent[2], 'Key2 was not in the iteration!');
CheckTrue(aPresent[3], 'Key3 was not in the iteration!');
end;
function THashesSITest.GetHash(): TX2SIHash;
begin
Result := TX2SIHash(FHash);
end;
{ THashesPOTest }
procedure THashesPOTest.SetUp;
begin
inherited;
FHash := TX2POHash.Create(True);
end;
procedure THashesPOTest.FillTestItems;
begin
Hash[Pointer(0)] := TObject0.Create();
Hash[Pointer(1)] := TObject1.Create();
Hash[Pointer(2)] := TObject2.Create();
end;
procedure THashesPOTest.testSet;
begin
FillTestItems();
CheckEquals(3, Hash.Count);
end;
procedure THashesPOTest.testGet;
begin
FillTestItems();
CheckTrue(Hash[Pointer(0)] is TObject0);
CheckTrue(Hash[Pointer(1)] is TObject1);
CheckTrue(Hash[Pointer(2)] is TObject2);
end;
procedure THashesPOTest.testDelete;
begin
FillTestItems();
Hash.Delete(Pointer(1));
CheckEquals(2, Hash.Count);
CheckTrue(Hash.Exists(Pointer(0)), 'Key1 does not exist!');
CheckFalse(Hash.Exists(Pointer(1)), 'Key2 still exists!');
CheckTrue(Hash.Exists(Pointer(2)), 'Key3 does not exist!');
end;
procedure THashesPOTest.testIterate;
var
aPresent: array[0..2] of Boolean;
begin
FillTestItems();
FillChar(aPresent, SizeOf(aPresent), #0);
Hash.First();
while Hash.Next() do
if ((Hash.CurrentKey = Pointer(0)) and (Hash.CurrentValue is TObject0)) or
((Hash.CurrentKey = Pointer(1)) and (Hash.CurrentValue is TObject1)) or
((Hash.CurrentKey = Pointer(2)) and (Hash.CurrentValue is TObject2)) then
aPresent[Integer(Hash.CurrentKey)] := True;
CheckTrue(aPresent[0], 'Key1 was not in the iteration!');
CheckTrue(aPresent[1], 'Key2 was not in the iteration!');
CheckTrue(aPresent[2], 'Key3 was not in the iteration!');
end;
function THashesPOTest.GetHash(): TX2POHash;
begin
Result := TX2POHash(FHash);
end;
initialization
RegisterTest('Hashes', THashesSITest.Suite);
RegisterTest('Hashes', THashesPOTest.Suite);
end.

View File

@ -105,10 +105,6 @@ HostApplication=
Launcher= Launcher=
UseLauncher=0 UseLauncher=0
DebugCWD= DebugCWD=
[Language]
ActiveLang=
ProjectLang=
RootDir=
[Version Info] [Version Info]
IncludeVerInfo=0 IncludeVerInfo=0
AutoIncBuild=0 AutoIncBuild=0

View File

@ -1,12 +1,14 @@
program X2UtUnitTests; program X2UtUnitTests;
uses uses
MemCheck,
TestFramework, TestFramework,
GUITestRunner, GUITestRunner,
UBits in 'Units\UBits.pas', BitsTest in 'Units\BitsTest.pas',
UTrees in 'Units\UTrees.pas'; HashesTest in 'Units\HashesTest.pas';
begin begin
MemChk();
RunRegisteredTests(); RunRegisteredTests();
end. end.

View File

@ -194,6 +194,8 @@ type
constructor Create(); virtual; constructor Create(); virtual;
destructor Destroy(); override; destructor Destroy(); override;
procedure Clear();
procedure First(); procedure First();
function Next(): Boolean; function Next(): Boolean;
@ -713,7 +715,7 @@ end;
function TX2CustomHashManager.ToPointer(const AValue: Pointer; function TX2CustomHashManager.ToPointer(const AValue: Pointer;
const ASize: Cardinal): Pointer; const ASize: Cardinal): Pointer;
begin begin
Result := Pointer(AValue); Result := Pointer(AValue^);
end; end;
function TX2CustomHashManager.ToValue(const AData: Pointer; function TX2CustomHashManager.ToValue(const AData: Pointer;
@ -726,7 +728,7 @@ end;
function TX2CustomHashManager.Compare(const AData: Pointer; const AValue: Pointer; function TX2CustomHashManager.Compare(const AData: Pointer; const AValue: Pointer;
const ASize: Cardinal): Boolean; const ASize: Cardinal): Boolean;
begin begin
Result := (Pointer(AValue) = AData); Result := (Pointer(AValue^) = AData);
end; end;
@ -735,7 +737,7 @@ end;
========================================} ========================================}
function TX2HashPointerManager.ToPointer(const AValue: Pointer): Pointer; function TX2HashPointerManager.ToPointer(const AValue: Pointer): Pointer;
begin begin
Result := ToPointer(AValue, SizeOf(Pointer)); Result := ToPointer(@AValue, SizeOf(Pointer));
end; end;
function TX2HashPointerManager.ToValue(const AData: Pointer): Pointer; function TX2HashPointerManager.ToValue(const AData: Pointer): Pointer;
@ -749,7 +751,7 @@ end;
========================================} ========================================}
function TX2HashIntegerManager.ToPointer(const AValue: Integer): Pointer; function TX2HashIntegerManager.ToPointer(const AValue: Integer): Pointer;
begin begin
Result := ToPointer(Pointer(AValue), SizeOf(Integer)); Result := ToPointer(@AValue, SizeOf(Integer));
end; end;
function TX2HashIntegerManager.ToValue(const AData: Pointer): Integer; function TX2HashIntegerManager.ToValue(const AData: Pointer): Integer;
@ -771,7 +773,7 @@ end;
function TX2HashObjectManager.ToPointer(const AValue: TObject): Pointer; function TX2HashObjectManager.ToPointer(const AValue: TObject): Pointer;
begin begin
Result := ToPointer(Pointer(AValue), SizeOf(Integer)); Result := ToPointer(@AValue, SizeOf(Integer));
end; end;
function TX2HashObjectManager.ToValue(const AData: Pointer): TObject; function TX2HashObjectManager.ToValue(const AData: Pointer): TObject;
@ -871,42 +873,8 @@ begin
end; end;
destructor TX2CustomHash.Destroy(); destructor TX2CustomHash.Destroy();
procedure DestroyBucket(const ABucket: PX2HashBucket);
var
iItem: Integer;
pNext: PX2HashValue;
pValue: PX2HashValue;
begin
for iItem := Pred(LeafSize) downto 0 do
if ABucket^.Items[iItem] <> nil then
case ABucket^.Items[iItem].ID of
HIDBucket:
DestroyBucket(PX2HashBucket(ABucket^.Items[iItem]));
HIDValue:
begin
pValue := PX2HashValue(ABucket^.Items[iItem]);
repeat
FKeyManager.Finalize(pValue^.Key);
FValueManager.Finalize(pValue^.Value);
pNext := pValue^.Next;
FreeMem(pValue, SizeOf(TX2HashValue));
pValue := pNext;
until pValue = nil;
end;
end;
FreeMem(ABucket, SizeOf(TX2HashBucket));
end;
begin begin
if Assigned(FRoot) then Clear();
begin
DestroyBucket(FRoot);
FRoot := nil;
end;
FreeAndNil(FValueManager); FreeAndNil(FValueManager);
FreeAndNil(FKeyManager); FreeAndNil(FKeyManager);
FreeAndNil(FCursor); FreeAndNil(FCursor);
@ -1134,6 +1102,47 @@ begin
AAllowCreate); AAllowCreate);
end; end;
procedure TX2CustomHash.Clear();
procedure DestroyBucket(const ABucket: PX2HashBucket);
var
iItem: Integer;
pNext: PX2HashValue;
pValue: PX2HashValue;
begin
for iItem := Pred(LeafSize) downto 0 do
if ABucket^.Items[iItem] <> nil then
case ABucket^.Items[iItem].ID of
HIDBucket:
DestroyBucket(PX2HashBucket(ABucket^.Items[iItem]));
HIDValue:
begin
pValue := PX2HashValue(ABucket^.Items[iItem]);
repeat
FKeyManager.Finalize(pValue^.Key);
FValueManager.Finalize(pValue^.Value);
pNext := pValue^.Next;
FreeMem(pValue, SizeOf(TX2HashValue));
pValue := pNext;
until pValue = nil;
end;
end;
FreeMem(ABucket, SizeOf(TX2HashBucket));
end;
begin
if FRoot <> nil then
begin
DestroyBucket(FRoot);
FCount := 0;
FRoot := nil;
end;
end;
function TX2CustomHash.Exists(const AKey: Pointer; function TX2CustomHash.Exists(const AKey: Pointer;
const ASize: Cardinal): Boolean; const ASize: Cardinal): Boolean;
begin begin