lazarus/components/tachart/test/UtilsTest.pas

520 lines
13 KiB
ObjectPascal

{
*****************************************************************************
* See the file COPYING.modifiedLGPL.txt, included in this distribution,
* for details about the license.
*****************************************************************************
Authors: Alexander Klenin
}
unit UtilsTest;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FPCUnit, TestRegistry, TAChartUtils;
type
TIntervalListTest = class(TTestCase)
strict private
FIList: TIntervalList;
protected
procedure SetUp; override;
procedure TearDown; override;
published
procedure Basic;
procedure Intersect;
procedure Merge;
end;
TMathTest = class(TTestCase)
published
procedure CumulNurmDistrTest;
procedure TestIsEquivalent;
end;
TGeometryTest = class(TTestCase)
strict private
procedure AssertEquals(const Expected, Actual: TDoublePoint); overload;
procedure AssertEquals(const Expected, Actual: TPoint); overload;
procedure AssertEquals(const Expected, Actual: TRect); overload;
published
procedure TestExpandRect;
procedure TestLineIntersectsLine;
procedure TestLineIntersectsRect;
procedure TestPointInPolygon;
procedure TestPointOnLine;
procedure TestPointOperations;
procedure TestPolygonIntersectsPolygon;
end;
TColorTest = class(TTestCase)
strict private
procedure AssertEqualsHex(Expected, Actual: Integer); overload;
published
procedure TestInterpolate;
end;
TRTTITest = class(TTestCase)
published
procedure TestSetPropDefaults;
end;
TPublishedIntegerSetTest = class(TTestCase)
strict private
FISet: TPublishedIntegerSet;
protected
procedure SetUp; override;
published
procedure TestAsBooleans;
procedure TestAsString;
procedure TestIsSet;
end;
type
THistoryTest = class(TTestCase)
published
procedure TestHistory;
end;
implementation
uses
Math, TAGeometry, TAMath, AssertHelpers;
{ TIntervalListTest }
procedure TIntervalListTest.Basic;
begin
AssertEquals(0, FIList.IntervalCount);
FIList.AddRange(1.0, 2.0);
AssertEquals(1, FIList.IntervalCount);
FIList.AddPoint(3.0);
AssertEquals(2, FIList.IntervalCount);
AssertEquals(3.0, FIList.Interval[1].FEnd);
FIList.Clear;
AssertEquals(0, FIList.IntervalCount);
end;
procedure TIntervalListTest.Intersect;
var
l, r: Double;
hint: Integer = 0;
begin
FIList.Clear;
FIList.AddRange(1.0, 2.0);
l := 5.0;
r := 6.0;
AssertFalse(FIList.Intersect(l, r, hint));
l := 1.5;
r := 6.0;
AssertTrue(FIList.Intersect(l, r, hint));
AssertEquals(2.0, r);
FIList.Epsilon := 0.1;
l := 0.5;
r := 2.5;
AssertTrue(FIList.Intersect(l, r, hint));
AssertEquals(0.9, l);
AssertEquals(2.1, r);
end;
procedure TIntervalListTest.Merge;
begin
FIList.Clear;
FIList.AddRange(1.0, 2.0);
FIList.AddRange(3.0, 4.0);
AssertEquals(2, FIList.IntervalCount);
FIList.AddRange(1.5, 2.5);
AssertEquals(2, FIList.IntervalCount);
AssertEquals(2.5, FIList.Interval[0].FEnd);
FIList.AddRange(3.5, 3.6);
AssertEquals(2, FIList.IntervalCount);
FIList.AddRange(2.5, 3.0);
AssertEquals(1, FIList.IntervalCount);
FIList.AddPoint(4.0);
AssertEquals(1, FIList.IntervalCount);
FIList.AddPoint(4.1);
AssertEquals(2, FIList.IntervalCount);
end;
procedure TIntervalListTest.SetUp;
begin
inherited SetUp;
FIList := TIntervalList.Create;
end;
procedure TIntervalListTest.TearDown;
begin
inherited TearDown;
FreeAndNil(FIList);
end;
{ TMathTest }
procedure TMathTest.CumulNurmDistrTest;
const
INV_PTS: array [1..3] of Double = (-1.5, 0.33, 2.0);
var
p: Double;
begin
AssertEquals(0, CumulNormDistr(0));
AssertEquals(0.84134, CumulNormDistr(1.0));
for p in INV_PTS do
AssertEquals(p, InvCumulNormDistr(CumulNormDistr(p)));
end;
procedure TMathTest.TestIsEquivalent;
begin
AssertTrue(IsEquivalent(1.2345, 1.2345));
AssertTrue(IsEquivalent(SafeNaN, SafeNaN));
AssertTrue(IsEquivalent(1e100, 1e100+1));
AssertFalse(IsEquivalent(1e10, 1e10+1));
AssertFalse(IsEquivalent(5, SafeNaN));
AssertFalse(IsEquivalent(SafeNaN, 5));
end;
{ TGeometryTest }
procedure TGeometryTest.AssertEquals(const Expected, Actual: TDoublePoint);
begin
AssertEquals(Expected.X, Actual.X);
AssertEquals(Expected.Y, Actual.Y);
end;
procedure TGeometryTest.AssertEquals(const Expected, Actual: TPoint);
begin
AssertEquals(Expected.X, Actual.X);
AssertEquals(Expected.Y, Actual.Y);
end;
procedure TGeometryTest.AssertEquals(const Expected, Actual: TRect);
begin
AssertEquals(Expected.TopLeft, Actual.TopLeft);
AssertEquals(Expected.BottomRight, Actual.BottomRight);
end;
procedure TGeometryTest.TestExpandRect;
var
r: TRect;
begin
r := ZeroRect;
ExpandRect(r, Point(1, 2));
AssertEquals(Rect(0, 0, 1, 2), r);
ExpandRect(r, Point(-5, -6));
AssertEquals(Rect(-5, -6, 1, 2), r);
r := Rect(100, 100, 0, 0);
ExpandRect(r, Point(3, 1));
AssertEquals(Rect(3, 1, 3, 1), r);
end;
procedure TGeometryTest.TestLineIntersectsLine;
var
p1, p2: TPoint;
begin
p1 := Point(0, 0);
p2 := Point(1, 1);
AssertTrue(IsLineIntersectsLine(Point(1, 0), Point(0, 1), p1, p2));
AssertTrue(IsLineIntersectsLine(Point(1, 0), Point(0, 0), p1, p2));
AssertTrue(IsLineIntersectsLine(Point(1, 1), Point(2, 2), p1, p2));
AssertFalse(IsLineIntersectsLine(Point(2, 2), Point(3, 3), p1, p2));
AssertTrue(IsLineIntersectsLine(Point(2, 0), Point(0, 2), p1, p2));
AssertFalse(IsLineIntersectsLine(Point(3, 0), Point(0, 3), p1, p2));
p2 := Point(1, 0);
AssertTrue(IsLineIntersectsLine(Point(0, 0), Point(2, 0), p1, p2));
AssertFalse(IsLineIntersectsLine(Point(0, 1), Point(1, 1), p1, p2));
end;
procedure TGeometryTest.TestLineIntersectsRect;
var
r: TDoubleRect = (a: (X: 0; Y: 0); b: (X: 20; Y: 10));
procedure Check(AP1, AP2, AR1, AR2: TDoublePoint);
begin
AssertTrue(LineIntersectsRect(AP1, AP2, r));
AssertEquals(AR1, AP1);
AssertEquals(AR2, AP2);
end;
var
p1, p2: TDoublePoint;
begin
p1 := DoublePoint(-1, -1);
p2 := DoublePoint(0, 20);
AssertFalse(LineIntersectsRect(p1, p2, r));
p1 := DoublePoint(100, 20);
AssertFalse(LineIntersectsRect(p1, p2, r));
p1 := DoublePoint(-1, -1);
p2 := DoublePoint(1, 1);
Check(p1, p2, DoublePoint(0, 0), p2);
p1 := DoublePoint(0, 0);
Check(p1, p2, p1, p2);
p1 := DoublePoint(20, 20);
p2 := DoublePoint(20, -10);
Check(p1, p2, DoublePoint(20, 10), DoublePoint(20, 0));
p1 := DoublePoint(10, 20);
p2 := DoublePoint(15, -10);
Check(p1, p2, DoublePoint(11.6667, 10), DoublePoint(13.3333, 0));
p1 := DoublePoint(10, 5);
p2 := DoublePoint(SafeInfinity, 5);
Check(p1, p2, p1, DoublePoint(20, 5));
p2 := DoublePoint(10, NegInfinity);
Check(p1, p2, p1, DoublePoint(10, 0));
end;
procedure TGeometryTest.TestPointInPolygon;
var
p: TPoint;
r: array [1..4] of TPoint =
((X: 0; Y: 0), (X: 10; Y: 0), (X: 10; Y: 5), (X: 0; Y: 5));
begin
p := Point(1, 1);
AssertFalse(IsPointInPolygon(p, []));
AssertTrue(IsPointInPolygon(p, [Point(0, 0), Point(0, 2), Point(3, 0)]));
AssertTrue(IsPointInPolygon(p, [Point(0, 0), Point(0, 2), Point(3, 1)]));
AssertTrue(IsPointInPolygon(p, [Point(0, 0), Point(0, 2), Point(1, 1)]));
AssertFalse(IsPointInPolygon(p, [Point(2, 0), Point(2, 2), Point(3, 1)]));
AssertFalse(IsPointInPolygon(p, [Point(2, 0), Point(1, 2), Point(0, 10)]));
AssertTrue(IsPointInPolygon(Point(5, 5), r));
AssertTrue(IsPointInPolygon(Point(10, 5), r));
AssertFalse(IsPointInPolygon(Point(11, 5), r));
AssertFalse(IsPointInPolygon(Point(0, -1), r));
end;
procedure TGeometryTest.TestPointOnLine;
begin
AssertTrue(IsPointOnLine(Point(0, 0), Point(-1, -1), Point(1, 1)));
AssertFalse(IsPointOnLine(Point(1, 0), Point(-1, -1), Point(1, 1)));
AssertTrue(IsPointOnLine(Point(0, 0), Point(0, -1), Point(0, 1)));
AssertFalse(IsPointOnLine(Point(-1, 0), Point(0, -1), Point(0, 1)));
AssertTrue(IsPointOnLine(Point(0, 0), Point(-1, 0), Point(1, 0)));
AssertFalse(IsPointOnLine(Point(0, 1), Point(-1, 0), Point(1, 0)));
end;
procedure TGeometryTest.TestPointOperations;
begin
AssertEquals(Point(1, 0), RotatePoint(Point(1, 0), 0.0));
AssertEquals(Point(0, 1), RotatePoint(Point(1, 0), Pi / 2));
AssertEquals(Point(14, 0), RotatePoint(Point(10, 10), -Pi / 4));
end;
procedure TGeometryTest.TestPolygonIntersectsPolygon;
function OffsetPolygon(AP: array of TPoint; AOffset: TPoint): TPointArray;
var
i: Integer;
begin
SetLength(Result, Length(AP));
for i := 0 to High(AP) do
Result[i] := AP[i] + AOffset;
end;
var
p1: array [1..4] of TPoint =
((X: 0; Y: 0), (X: 10; Y: 0), (X: 10; Y: 5), (X: 0; Y: 5));
begin
AssertTrue(IsPolygonIntersectsPolygon(p1, OffsetPolygon(p1, Point(0, 0))));
AssertTrue(IsPolygonIntersectsPolygon(p1, OffsetPolygon(p1, Point(1, 1))));
AssertTrue(IsPolygonIntersectsPolygon(p1, OffsetPolygon(p1, Point(5, 0))));
AssertTrue(IsPolygonIntersectsPolygon(p1, OffsetPolygon(p1, Point(10, 0))));
AssertFalse(IsPolygonIntersectsPolygon(p1, OffsetPolygon(p1, Point(11, 0))));
AssertFalse(IsPolygonIntersectsPolygon(p1, OffsetPolygon(p1, Point(0, -6))));
end;
{ TColorTest }
procedure TColorTest.AssertEqualsHex(Expected, Actual: Integer);
begin
AssertTrue(
ComparisonMsg(IntToHex(Expected, 8), IntToHex(Actual, 8)),
Expected = Actual);
end;
procedure TColorTest.TestInterpolate;
begin
AssertEqualsHex($01020304, InterpolateRGB($01020304, $00787980, 0.0));
AssertEqualsHex($00787980, InterpolateRGB($01020304, $00787980, 1.0));
AssertEqualsHex($003D3E42, InterpolateRGB($01020304, $00787980, 0.5));
AssertEqualsHex($01010102, InterpolateRGB($01010100, $02020214, 0.1));
end;
type
TE = (eA, eB, eC);
TESet = set of TE;
T1 = class(TPersistent)
private
FP1: Integer;
FP2: Boolean;
FP3: TESet;
procedure SetP2(AValue: Boolean);
public
constructor Create;
published
property P1: Integer read FP1 write FP1 default 5;
property P2: Boolean read FP2 write SetP2 default true;
property P3: TESet read FP3 write FP3 default [eC];
end;
T2 = class(T1)
published
property P1 default 6;
property P3 default [eA];
end;
{ T1 }
constructor T1.Create;
begin
SetPropDefaults(Self, ['P1', 'P2', 'P3']);
end;
procedure T1.SetP2(AValue: Boolean);
begin
FP2 := AValue;
end;
{ TRTTITest }
procedure TRTTITest.TestSetPropDefaults;
var
v1: T1;
v2: T2;
begin
v1 := T1.Create;
AssertEquals(5, v1.P1);
AssertTrue(v1.P2);
AssertTrue(v1.P3 = [eC]);
v1.Free;
v2 := T2.Create;
AssertEquals(6, v2.P1);
AssertTrue(v2.P2);
AssertTrue(v2.P3 = [eA]);
v2.Free;
end;
{ TPublishedIntegerSetTest }
procedure TPublishedIntegerSetTest.SetUp;
begin
inherited SetUp;
FISet.Init;
end;
procedure TPublishedIntegerSetTest.TestAsBooleans;
procedure AssertBooleans(const AExpected: array of Boolean; ACount: Integer);
begin
AssertEquals(AExpected, FISet.AsBooleans(ACount));
end;
begin
AssertBooleans([], 0);
FISet.AllSet := false;
FISet.IsSet[2] := true;
AssertBooleans([false, false, true], 3);
FISet.AllSet := true;
AssertBooleans([true, true, true, true], 4);
end;
procedure TPublishedIntegerSetTest.TestAsString;
begin
AssertTrue(FISet.AllSet);
AssertEquals(PUB_INT_SET_ALL, FISet.AsString);
FISet.AllSet := false;
AssertFalse(FISet.AllSet);
AssertEquals(PUB_INT_SET_EMPTY, FISet.AsString);
FISet.AsString := '3 ,1,, 2';
AssertEquals('3,1,2', FISet.AsString);
FISet.AsString := PUB_INT_SET_ALL;
AssertTrue(FISet.AllSet);
FISet.AsString := '+';
AssertEquals(PUB_INT_SET_EMPTY, FISet.AsString);
end;
procedure TPublishedIntegerSetTest.TestIsSet;
begin
AssertTrue(FISet.AllSet);
AssertTrue(FISet.IsSet[100000]);
FISet.AllSet := false;
AssertFalse(FISet.IsSet[100000]);
FISet.IsSet[99] := true;
AssertEquals('99', FISet.AsString);
FISet.AsString := '3,5';
AssertTrue(FISet.IsSet[3]);
AssertFalse(FISet.IsSet[99]);
FISet.IsSet[3] := false;
FISet.IsSet[5] := false;
AssertEquals(PUB_INT_SET_EMPTY, FISet.AsString);
end;
// Workaround: FPC 2.6 fails if this type is made local to TestHistory.
type
TCharHistory = specialize THistory<Char>;
{ THistoryTest }
procedure THistoryTest.TestHistory;
var
h: TCharHistory;
procedure Check(AMessage, AExpected: String);
var
actual: String = '';
i: Integer;
begin
for i := 0 to h.Count - 1 do
actual += h.Item[i];
AssertEquals(AMessage, AExpected, actual);
end;
begin
h := TCharHistory.Create;
try
AssertEquals('Initial capacity', 0, h.Capacity);
Check('Initial state', '');
h.Add('a');
Check('Zero capacity', '');
h.Capacity := 3;
h.Add('a');
h.Add('b');
Check('Normal', 'ab');
h.Add('c');
h.Add('d');
Check('Overflow', 'bcd');
h.Capacity := 2;
Check('Reduce capacity 1', 'cd');
h.Add('e');
Check('Reduce capacity 2', 'de');
AssertEquals('Item[-1]', 'e', h[-1]);
AssertEquals('Pop', 'e', h.Pop);
Check('After pop', 'd');
finally
FreeAndNil(h);
end;
end;
initialization
RegisterTests([
TIntervalListTest, TMathTest, TGeometryTest, TColorTest, TRTTITest,
TPublishedIntegerSetTest, THistoryTest]);
end.