DateTime unit test

This commit is contained in:
Michael Schimmel
2025-11-23 22:44:56 +01:00
parent 2f87444827
commit c8e0c78e3f
3 changed files with 163 additions and 1 deletions
+160
View File
@@ -0,0 +1,160 @@
unit Test.Myc.Ast.RTL.DateTime;
interface
uses
DUnitX.TestFramework,
System.SysUtils,
System.DateUtils,
System.Math,
Myc.Ast.Environment,
Myc.Ast.Script,
Myc.Data.Value,
Myc.Data.Scalar;
type
[TestFixture]
[IgnoreMemoryLeaks]
TTestRtlDateTime = class
private
FEnv: TAstEnvironment;
public
[Setup]
procedure Setup;
[Teardown]
procedure Teardown;
[Test]
procedure Test_Constructor_FixedDate;
[Test]
procedure Test_Constructor_Now;
[Test]
[TestCase('Later', '2025,1,1,2024,1,1,True')]
[TestCase('Earlier', '2020,1,1,2021,1,1,False')]
procedure Test_GreaterThan(Y1, M1, D1, Y2, M2, D2: Integer; ExpectTrue: Boolean);
[Test]
procedure Test_Equality;
[Test]
procedure Test_DateTime_Is_Truthy;
[Test]
procedure Test_Round_DateTime;
end;
implementation
procedure TTestRtlDateTime.Setup;
begin
// Creates a fresh environment with all RTL functions registered
// (including Date, Now, True, False)
FEnv := TAstEnvironment.Construct(nil);
end;
procedure TTestRtlDateTime.Teardown;
begin
// Environment is a record (interface wrapper), automatic cleanup
end;
procedure TTestRtlDateTime.Test_Constructor_FixedDate;
var
Res: TDataValue;
Expected: TDateTime;
begin
// Act
Res := FEnv.Run(TAstScript.Parse('(Date 2025 11 24)'));
// Assert
Assert.AreEqual(TDataValueKind.vkScalar, Res.Kind, 'Result should be scalar');
Assert.AreEqual(TScalar.TKind.DateTime, Res.AsScalar.Kind, 'Scalar kind should be DateTime');
Expected := EncodeDate(2025, 11, 24);
Assert.AreEqual(Expected, Res.AsScalar.Value.AsDouble, 0.0001, 'Date value mismatch');
end;
procedure TTestRtlDateTime.Test_Constructor_Now;
var
Res: TDataValue;
Before, After: TDateTime;
begin
Before := System.SysUtils.Now;
// Allow small window for execution time
Sleep(1);
// Act
Res := FEnv.Run(TAstScript.Parse('(Now)'));
After := System.SysUtils.Now;
// Assert
Assert.AreEqual(TScalar.TKind.DateTime, Res.AsScalar.Kind);
// Check if result is within the time window
Assert.IsTrue(Res.AsScalar.Value.AsDouble >= Before);
Assert.IsTrue(Res.AsScalar.Value.AsDouble <= After);
end;
procedure TTestRtlDateTime.Test_GreaterThan(Y1, M1, D1, Y2, M2, D2: Integer; ExpectTrue: Boolean);
var
Script: string;
Res: TDataValue;
begin
// (> (Date y1 m1 d1) (Date y2 m2 d2))
Script := Format('(> (Date %d %d %d) (Date %d %d %d))', [Y1, M1, D1, Y2, M2, D2]);
Res := FEnv.Run(TAstScript.Parse(Script));
Assert.AreEqual(TScalar.TKind.Boolean, Res.AsScalar.Kind);
if ExpectTrue then
Assert.AreEqual(Int64(1), Res.AsScalar.Value.AsInt64, 'Expected True')
else
Assert.AreEqual(Int64(0), Res.AsScalar.Value.AsInt64, 'Expected False');
end;
procedure TTestRtlDateTime.Test_Equality;
var
Res: TDataValue;
begin
// (= (Date 2023 10 10) (Date 2023 10 10))
Res := FEnv.Run(TAstScript.Parse('(= (Date 2023 10 10) (Date 2023 10 10))'));
Assert.AreEqual(TScalar.TKind.Boolean, Res.AsScalar.Kind);
Assert.AreEqual(Int64(1), Res.AsScalar.Value.AsInt64);
end;
procedure TTestRtlDateTime.Test_DateTime_Is_Truthy;
var
Res: TDataValue;
begin
// (if (Date 2023 1 1) "yes" "no")
// Checks if IsTruthy correctly handles TKind.DateTime
Res := FEnv.Run(TAstScript.Parse('(if (Date 2023 1 1) "yes" "no")'));
Assert.AreEqual(TDataValueKind.vkText, Res.Kind);
Assert.AreEqual('yes', Res.AsText);
end;
procedure TTestRtlDateTime.Test_Round_DateTime;
var
Res: TDataValue;
InputDate: TDateTime;
Expected: Int64;
begin
// Ensure RTL Round handles DateTime as float
// (Round (Date 2023 11 24))
// Date creates a TDateTime (Double) with 0.0 time fraction, so Round should return the truncation.
InputDate := EncodeDate(2023, 11, 24);
Expected := System.Round(InputDate);
Res := FEnv.Run(TAstScript.Parse('(Round (Date 2023 11 24))'));
Assert.AreEqual(TScalar.TKind.Ordinal, Res.AsScalar.Kind);
Assert.AreEqual(Expected, Res.AsScalar.Value.AsInt64);
end;
end.
+2 -1
View File
@@ -30,7 +30,8 @@ uses
Test.Myc.Ast.Scope in 'AST\Test.Myc.Ast.Scope.pas', Test.Myc.Ast.Scope in 'AST\Test.Myc.Ast.Scope.pas',
Test.Myc.Ast.RTL in 'AST\Test.Myc.Ast.RTL.pas', Test.Myc.Ast.RTL in 'AST\Test.Myc.Ast.RTL.pas',
Test.Myc.Ast.Script in 'AST\Test.Myc.Ast.Script.pas', Test.Myc.Ast.Script in 'AST\Test.Myc.Ast.Script.pas',
Test.Myc.Ast.Compiler.Macros in 'AST\Test.Myc.Ast.Compiler.Macros.pas'; Test.Myc.Ast.Compiler.Macros in 'AST\Test.Myc.Ast.Compiler.Macros.pas',
Test.Myc.Ast.RTL.DateTime in 'AST\Test.Myc.Ast.RTL.DateTime.pas';
{ keep comment here to protect the following conditional from being removed by the IDE when adding a unit } { keep comment here to protect the following conditional from being removed by the IDE when adding a unit }
{$IFNDEF TESTINSIGHT} {$IFNDEF TESTINSIGHT}
+1
View File
@@ -132,6 +132,7 @@ $(PreBuildEvent)]]></PreBuildEvent>
<DCCReference Include="AST\Test.Myc.Ast.RTL.pas"/> <DCCReference Include="AST\Test.Myc.Ast.RTL.pas"/>
<DCCReference Include="AST\Test.Myc.Ast.Script.pas"/> <DCCReference Include="AST\Test.Myc.Ast.Script.pas"/>
<DCCReference Include="AST\Test.Myc.Ast.Compiler.Macros.pas"/> <DCCReference Include="AST\Test.Myc.Ast.Compiler.Macros.pas"/>
<DCCReference Include="AST\Test.Myc.Ast.RTL.DateTime.pas"/>
<BuildConfiguration Include="Base"> <BuildConfiguration Include="Base">
<Key>Base</Key> <Key>Base</Key>
</BuildConfiguration> </BuildConfiguration>