Files
MycLib/Test/AST/Test.Myc.Ast.RTL.DateTime.pas
Michael Schimmel 717a648ad4 RTL: Sqrt & Pow
2026-01-13 11:36:59 +01:00

161 lines
4.3 KiB
ObjectPascal

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.