New type system - Decimals
This commit is contained in:
+57
-62
@@ -86,7 +86,7 @@ begin
|
||||
Assert.AreNotSame(IDataRecordType(personType1), IDataRecordType(otherType), 'Different definitions should result in different types');
|
||||
|
||||
// --- 3. Test Value Creation and Access ---
|
||||
personValue := personType1.CreateValue([TDataType.FromOrdinal(123), TDataType.FromFloat(45.67)]);
|
||||
personValue := personType1.CreateValue([TDataType.Ordinal.CreateValue(123), TDataType.Float.CreateValue(45.67)]);
|
||||
|
||||
Assert.IsNotNull(personValue, 'RecordValue should be created');
|
||||
Assert.AreSame(IDataRecordType(personType1), personValue.DataType, 'Value should have the correct data type');
|
||||
@@ -111,7 +111,7 @@ begin
|
||||
|
||||
// Test for wrong number of items during value creation
|
||||
Assert.WillRaise(
|
||||
procedure begin personType1.CreateValue([TDataType.FromOrdinal(99)]); end,
|
||||
procedure begin personType1.CreateValue([TDataType.Ordinal.CreateValue(99)]); end,
|
||||
EArgumentException,
|
||||
'Wrong number of items should raise exception'
|
||||
);
|
||||
@@ -121,7 +121,7 @@ begin
|
||||
procedure
|
||||
begin
|
||||
// Passing Float instead of Integer for the first item
|
||||
personType1.CreateValue([TDataType.FromFloat(1.0), TDataType.FromFloat(2.0)]);
|
||||
personType1.CreateValue([TDataType.Float.CreateValue(1.0), TDataType.Float.CreateValue(2.0)]);
|
||||
end,
|
||||
EArgumentException,
|
||||
'Wrong item type should raise exception'
|
||||
@@ -142,7 +142,8 @@ begin
|
||||
TRecordField.Create('C', TDataType.Float)
|
||||
]
|
||||
);
|
||||
dataValue := dataType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromText('two'), TDataType.FromFloat(3.0)]);
|
||||
dataValue :=
|
||||
dataType.CreateValue([TDataType.Ordinal.CreateValue(1), TDataType.Text.CreateValue('two'), TDataType.Float.CreateValue(3.0)]);
|
||||
|
||||
Assert.IsNotNull(dataValue, 'Generic record value should be created');
|
||||
Assert.AreEqual(3, dataType.FieldCount, 'Generic record should have 3 fields');
|
||||
@@ -161,11 +162,11 @@ var
|
||||
begin
|
||||
// This test covers optimized implementations for 1 and 2 elements.
|
||||
// --- 1. Setup: Create some values ---
|
||||
intValue := TDataType.FromOrdinal(123);
|
||||
floatValue := TDataType.FromFloat(45.67);
|
||||
intValue := TDataType.Ordinal.CreateValue(123);
|
||||
floatValue := TDataType.Float.CreateValue(45.67);
|
||||
|
||||
// --- 2. Test Value Creation and basic properties ---
|
||||
tuple1 := TDataType.FromTuple([intValue, floatValue]);
|
||||
tuple1 := TDataType.Tuple.CreateValue([intValue, floatValue]);
|
||||
|
||||
Assert.IsNotNull(tuple1, 'Tuple value should be created');
|
||||
Assert.AreEqual(2, tuple1.ItemCount, 'ItemCount should be on the value');
|
||||
@@ -174,8 +175,8 @@ begin
|
||||
|
||||
// --- 3. Test Singleton Type Behavior ---
|
||||
// Create more tuples with different structures
|
||||
tuple2 := TDataType.FromTuple([TDataType.FromOrdinal(99), TDataType.FromFloat(1.1)]);
|
||||
tuple3 := TDataType.FromTuple([intValue]);
|
||||
tuple2 := TDataType.Tuple.CreateValue([TDataType.Ordinal.CreateValue(99), TDataType.Float.CreateValue(1.1)]);
|
||||
tuple3 := TDataType.Tuple.CreateValue([intValue]);
|
||||
|
||||
// Access the DataType via the underlying interface
|
||||
type1 := tuple1.DataType;
|
||||
@@ -196,14 +197,14 @@ var
|
||||
begin
|
||||
// Test the generic implementation for tuples with > 5 elements.
|
||||
tupleValue :=
|
||||
TDataType.FromTuple(
|
||||
TDataType.Tuple.CreateValue(
|
||||
[
|
||||
TDataType.FromOrdinal(1),
|
||||
TDataType.FromOrdinal(2),
|
||||
TDataType.FromOrdinal(3),
|
||||
TDataType.FromOrdinal(4),
|
||||
TDataType.FromOrdinal(5),
|
||||
TDataType.FromOrdinal(6)
|
||||
TDataType.Ordinal.CreateValue(1),
|
||||
TDataType.Ordinal.CreateValue(2),
|
||||
TDataType.Ordinal.CreateValue(3),
|
||||
TDataType.Ordinal.CreateValue(4),
|
||||
TDataType.Ordinal.CreateValue(5),
|
||||
TDataType.Ordinal.CreateValue(6)
|
||||
]
|
||||
);
|
||||
|
||||
@@ -247,8 +248,8 @@ begin
|
||||
Assert.AreEqual('Array<Float>', TDataType(floatArrayType).Name, 'Type name should be Array<Float>');
|
||||
|
||||
// --- 3. Test Value Creation and Access ---
|
||||
v1 := TDataType.FromOrdinal(10);
|
||||
v2 := TDataType.FromOrdinal(20);
|
||||
v1 := TDataType.Ordinal.CreateValue(10);
|
||||
v2 := TDataType.Ordinal.CreateValue(20);
|
||||
arrayValue := intArrayType1.CreateValue([v1, v2]);
|
||||
|
||||
Assert.IsNotNull(arrayValue, 'ArrayValue should be created');
|
||||
@@ -267,7 +268,7 @@ begin
|
||||
procedure
|
||||
begin
|
||||
// Try to add a float value to an Array<Integer>
|
||||
intArrayType1.CreateValue([v1, TDataType.FromFloat(3.14)]);
|
||||
intArrayType1.CreateValue([v1, TDataType.Float.CreateValue(3.14)]);
|
||||
end,
|
||||
EArgumentException,
|
||||
'Wrong element type should raise an exception'
|
||||
@@ -290,14 +291,15 @@ begin
|
||||
Assert.AreEqual('[]', empty1.AsString, 'Empty array AsString is incorrect');
|
||||
|
||||
// Test optimized path for 1 element
|
||||
single := arrayType.CreateValue([TDataType.FromOrdinal(42)]);
|
||||
single := arrayType.CreateValue([TDataType.Ordinal.CreateValue(42)]);
|
||||
Assert.IsNotNull(single, 'Single element array should be created');
|
||||
Assert.AreEqual(1, single.ElementCount, 'Single element array should have 1 element');
|
||||
Assert.AreEqual(Int64(42), TDataType.TValue(single.Items[0]).AsOrdinal.Value, 'Single element value is incorrect');
|
||||
Assert.AreEqual('[42]', single.AsString, 'Single element array AsString is incorrect');
|
||||
|
||||
// Test generic path for > 1 elements
|
||||
generic := arrayType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromOrdinal(2), TDataType.FromOrdinal(3)]);
|
||||
generic :=
|
||||
arrayType.CreateValue([TDataType.Ordinal.CreateValue(1), TDataType.Ordinal.CreateValue(2), TDataType.Ordinal.CreateValue(3)]);
|
||||
Assert.IsNotNull(generic, 'Generic array should be created');
|
||||
Assert.AreEqual(3, generic.ElementCount, 'Generic array should have 3 elements');
|
||||
Assert.AreEqual('[1, 2, 3]', generic.AsString, 'Generic array AsString is incorrect');
|
||||
@@ -317,22 +319,22 @@ begin
|
||||
Assert.AreEqual(dkText, TDataType(textType).Kind, 'Type kind should be dkText');
|
||||
|
||||
// --- 2. Test Value Creation and Access ---
|
||||
textValue1 := TDataType.FromText('Hello World');
|
||||
textValue1 := TDataType.Text.CreateValue('Hello World');
|
||||
|
||||
Assert.IsNotNull(textValue1, 'TextValue should be created');
|
||||
Assert.AreSame(IDataType(textType), textValue1.DataType, 'Value should have the correct data type');
|
||||
Assert.AreEqual('Hello World', textValue1.Value, 'Value should be ''Hello World''');
|
||||
|
||||
// Test another text value
|
||||
textValue2 := TDataType.FromText('Delphi');
|
||||
textValue2 := TDataType.Text.CreateValue('Delphi');
|
||||
Assert.AreEqual('Delphi', textValue2.Value, 'Value should be ''Delphi''');
|
||||
|
||||
// --- 3. Test AsText casting ---
|
||||
dataValue := TDataType.FromText('Test Text');
|
||||
dataValue := TDataType.Text.CreateValue('Test Text');
|
||||
Assert.AreEqual('Test Text', TDataType.TValue(dataValue).AsText.Value, 'AsText should return correct value');
|
||||
|
||||
// Test invalid cast
|
||||
dataValue := TDataType.FromOrdinal(123);
|
||||
dataValue := TDataType.Ordinal.CreateValue(123);
|
||||
Assert.WillRaise(
|
||||
procedure begin TDataType.TValue(dataValue).AsText; end,
|
||||
EInvalidCast,
|
||||
@@ -345,8 +347,8 @@ var
|
||||
empty1, empty2: IDataTextValue;
|
||||
begin
|
||||
// Test the singleton implementation for the empty string.
|
||||
empty1 := TDataType.FromText('');
|
||||
empty2 := TDataType.FromText('');
|
||||
empty1 := TDataType.Text.CreateValue('');
|
||||
empty2 := TDataType.Text.CreateValue('');
|
||||
|
||||
Assert.IsNotNull(empty1, 'Empty text value should be created');
|
||||
Assert.AreSame(empty1, empty2, 'Empty text value should be a singleton');
|
||||
@@ -359,22 +361,22 @@ var
|
||||
zero1, zero2, nan1, nan2, generic: IDataFloatValue;
|
||||
begin
|
||||
// Test singleton for 0.0
|
||||
zero1 := TDataType.FromFloat(0.0);
|
||||
zero2 := TDataType.FromFloat(0.0);
|
||||
zero1 := TDataType.Float.CreateValue(0.0);
|
||||
zero2 := TDataType.Float.CreateValue(0.0);
|
||||
Assert.IsNotNull(zero1, 'Zero float should be created');
|
||||
Assert.AreSame(zero1, zero2, 'Zero float should be a singleton');
|
||||
Assert.AreEqual(0.0, zero1.Value, 'Value of zero float is incorrect');
|
||||
|
||||
// Test singleton for NaN
|
||||
nan1 := TDataType.FromFloat(NaN);
|
||||
nan2 := TDataType.FromFloat(NaN);
|
||||
nan1 := TDataType.Float.CreateValue(NaN);
|
||||
nan2 := TDataType.Float.CreateValue(NaN);
|
||||
Assert.IsNotNull(nan1, 'NaN float should be created');
|
||||
Assert.AreSame(nan1, nan2, 'NaN float should be a singleton');
|
||||
Assert.IsTrue(IsNaN(nan1.Value), 'Value of NaN float should be NaN');
|
||||
Assert.AreEqual('NaN', nan1.AsString, 'NaN AsString is incorrect');
|
||||
|
||||
// Test generic path
|
||||
generic := TDataType.FromFloat(123.45);
|
||||
generic := TDataType.Float.CreateValue(123.45);
|
||||
Assert.IsNotNull(generic, 'Generic float should be created');
|
||||
Assert.AreNotSame(zero1, generic, 'Generic float should not be the zero singleton');
|
||||
Assert.AreNotSame(nan1, generic, 'Generic float should not be the NaN singleton');
|
||||
@@ -397,22 +399,22 @@ begin
|
||||
|
||||
// --- 2. Test Value Creation and Access ---
|
||||
now := System.Sysutils.Now;
|
||||
tsValue1 := TDataType.FromTimestamp(now);
|
||||
tsValue1 := TDataType.Timestamp.CreateValue(now);
|
||||
|
||||
Assert.IsNotNull(tsValue1, 'TimestampValue should be created');
|
||||
Assert.AreSame(IDataType(tsType), tsValue1.DataType, 'Value should have the correct data type');
|
||||
Assert.AreEqual(now, tsValue1.Value, 'Value should be the same');
|
||||
|
||||
// Test another text value
|
||||
tsValue2 := TDataType.FromTimestamp(Date);
|
||||
tsValue2 := TDataType.Timestamp.CreateValue(Date);
|
||||
Assert.AreEqual(Date, tsValue2.Value, 'Value should be the same');
|
||||
|
||||
// --- 3. Test AsTimestamp casting ---
|
||||
dataValue := TDataType.FromTimestamp(now);
|
||||
dataValue := TDataType.Timestamp.CreateValue(now);
|
||||
Assert.AreEqual(now, TDataType.TValue(dataValue).AsTimestamp.Value, 'AsTimestamp should return correct value');
|
||||
|
||||
// Test invalid cast
|
||||
dataValue := TDataType.FromOrdinal(123);
|
||||
dataValue := TDataType.Ordinal.CreateValue(123);
|
||||
Assert.WillRaise(
|
||||
procedure begin TDataType.TValue(dataValue).AsTimestamp; end,
|
||||
EInvalidCast,
|
||||
@@ -491,20 +493,20 @@ var
|
||||
now: TDateTime;
|
||||
begin
|
||||
// Ordinal
|
||||
ordinalValue := TDataType.FromOrdinal(123);
|
||||
ordinalValue := TDataType.Ordinal.CreateValue(123);
|
||||
Assert.AreEqual('123', ordinalValue.AsString, 'Ordinal AsString incorrect');
|
||||
|
||||
// Float
|
||||
floatValue := TDataType.FromFloat(45.67);
|
||||
floatValue := TDataType.Float.CreateValue(45.67);
|
||||
Assert.AreEqual(FloatToStr(45.67), floatValue.AsString, 'Float AsString incorrect');
|
||||
|
||||
// Text
|
||||
textValue := TDataType.FromText('Hello');
|
||||
textValue := TDataType.Text.CreateValue('Hello');
|
||||
Assert.AreEqual('Hello', textValue.AsString, 'Text AsString incorrect');
|
||||
|
||||
// Timestamp
|
||||
now := System.Sysutils.Now;
|
||||
tsValue := TDataType.FromTimestamp(now);
|
||||
tsValue := TDataType.Timestamp.CreateValue(now);
|
||||
Assert.AreEqual(DateTimeToStr(now), tsValue.AsString, 'Timestamp AsString incorrect');
|
||||
|
||||
// Enum
|
||||
@@ -514,16 +516,16 @@ begin
|
||||
|
||||
// Array
|
||||
intArrayType := TDataType.ArrayOf(TDataType.Ordinal);
|
||||
arrayValue := intArrayType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromOrdinal(2)]);
|
||||
arrayValue := intArrayType.CreateValue([TDataType.Ordinal.CreateValue(1), TDataType.Ordinal.CreateValue(2)]);
|
||||
Assert.AreEqual('[1, 2]', arrayValue.AsString, 'Array AsString incorrect');
|
||||
|
||||
// Record
|
||||
personType := TDataType.RecordOf([TRecordField.Create('ID', TDataType.Ordinal), TRecordField.Create('Name', TDataType.Text)]);
|
||||
recordValue := personType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromText('Bob')]);
|
||||
recordValue := personType.CreateValue([TDataType.Ordinal.CreateValue(1), TDataType.Text.CreateValue('Bob')]);
|
||||
Assert.AreEqual('<ID: 1, Name: Bob>', recordValue.AsString, 'Record AsString incorrect');
|
||||
|
||||
// Tuple
|
||||
tupleValue := TDataType.FromTuple([TDataType.FromOrdinal(10), TDataType.FromText('Tuple')]);
|
||||
tupleValue := TDataType.Tuple.CreateValue([TDataType.Ordinal.CreateValue(10), TDataType.Text.CreateValue('Tuple')]);
|
||||
Assert.AreEqual('(10, Tuple)', tupleValue.AsString, 'Tuple AsString incorrect');
|
||||
end;
|
||||
|
||||
@@ -537,21 +539,21 @@ var
|
||||
personType: TDataType.TRecord;
|
||||
begin
|
||||
// --- Ordinal ---
|
||||
dataValue := TDataType.FromOrdinal(123);
|
||||
dataValue := TDataType.Ordinal.CreateValue(123);
|
||||
tv := dataValue.AsTValue;
|
||||
Assert.IsFalse(tv.IsEmpty, 'Ordinal TValue should not be empty');
|
||||
Assert.AreEqual(tkInt64, tv.Kind, 'Ordinal TValue kind should be tkInt64');
|
||||
Assert.AreEqual(Int64(123), tv.AsInt64, 'Ordinal TValue content is incorrect');
|
||||
|
||||
// --- Float ---
|
||||
dataValue := TDataType.FromFloat(45.67);
|
||||
dataValue := TDataType.Float.CreateValue(45.67);
|
||||
tv := dataValue.AsTValue;
|
||||
Assert.IsFalse(tv.IsEmpty, 'Float TValue should not be empty');
|
||||
Assert.AreEqual(tkFloat, tv.Kind, 'Float TValue kind should be tkFloat');
|
||||
Assert.AreEqual(45.67, tv.AsExtended, 'Float TValue content is incorrect');
|
||||
|
||||
// --- Text ---
|
||||
dataValue := TDataType.FromText('Hello');
|
||||
dataValue := TDataType.Text.CreateValue('Hello');
|
||||
tv := dataValue.AsTValue;
|
||||
Assert.IsFalse(tv.IsEmpty, 'Text TValue should not be empty');
|
||||
Assert.AreEqual(tkUString, tv.Kind, 'Text TValue kind should be tkUString');
|
||||
@@ -559,7 +561,7 @@ begin
|
||||
|
||||
// --- Timestamp ---
|
||||
now := System.SysUtils.Now;
|
||||
dataValue := TDataType.FromTimestamp(now);
|
||||
dataValue := TDataType.Timestamp.CreateValue(now);
|
||||
tv := dataValue.AsTValue;
|
||||
Assert.IsFalse(tv.IsEmpty, 'Timestamp TValue should not be empty');
|
||||
Assert.AreEqual(tkFloat, tv.Kind, 'Timestamp TValue kind is incorrect');
|
||||
@@ -575,7 +577,7 @@ begin
|
||||
|
||||
// --- Array ---
|
||||
intArrayType := TDataType.ArrayOf(TDataType.Ordinal);
|
||||
dataValue := intArrayType.CreateValue([TDataType.FromOrdinal(10), TDataType.FromOrdinal(20)]);
|
||||
dataValue := intArrayType.CreateValue([TDataType.Ordinal.CreateValue(10), TDataType.Ordinal.CreateValue(20)]);
|
||||
tv := dataValue.AsTValue;
|
||||
Assert.IsFalse(tv.IsEmpty, 'Array TValue should not be empty');
|
||||
Assert.IsTrue(tv.IsArray, 'Array TValue should be an array');
|
||||
@@ -598,7 +600,7 @@ begin
|
||||
|
||||
// --- Record ---
|
||||
personType := TDataType.RecordOf([TRecordField.Create('ID', TDataType.Ordinal), TRecordField.Create('Name', TDataType.Text)]);
|
||||
dataValue := personType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromText('Bob')]);
|
||||
dataValue := personType.CreateValue([TDataType.Ordinal.CreateValue(1), TDataType.Text.CreateValue('Bob')]);
|
||||
tv := dataValue.AsTValue;
|
||||
Assert.IsFalse(tv.IsEmpty, 'Record TValue should not be empty');
|
||||
Assert.IsTrue(tv.IsArray, 'Record TValue should be represented as an array');
|
||||
@@ -608,7 +610,7 @@ begin
|
||||
Assert.AreEqual('Bob', tv.GetArrayElement(1).AsType<TValue>.AsString, 'Record TValue element 1 is incorrect');
|
||||
|
||||
// --- Tuple ---
|
||||
dataValue := TDataType.FromTuple([TDataType.FromOrdinal(99), TDataType.FromText('Red')]);
|
||||
dataValue := TDataType.Tuple.CreateValue([TDataType.Ordinal.CreateValue(99), TDataType.Text.CreateValue('Red')]);
|
||||
tv := dataValue.AsTValue;
|
||||
Assert.IsFalse(tv.IsEmpty, 'Tuple TValue should not be empty');
|
||||
Assert.IsTrue(tv.IsArray, 'Tuple TValue should be represented as an array');
|
||||
@@ -667,15 +669,15 @@ begin
|
||||
begin
|
||||
ordinalValue := AValue.AsOrdinal;
|
||||
val := ordinalValue.Value;
|
||||
Result := TDataType.FromText(val.ToString);
|
||||
Result := TDataType.Text.CreateValue(val.ToString);
|
||||
end;
|
||||
|
||||
methodValue := TDataType.FromMethod(methodType1, myFunc);
|
||||
methodValue := methodType1.CreateValue(myFunc);
|
||||
Assert.IsNotNull(methodValue, 'MethodValue should be created');
|
||||
Assert.AreSame(IDataType(methodType1), methodValue.DataType, 'Value should have the correct data type');
|
||||
|
||||
// --- 4. Test Execution (Simulated) ---
|
||||
inputValue := TDataType.FromOrdinal(42);
|
||||
inputValue := TDataType.Ordinal.CreateValue(42);
|
||||
// Execute the function retrieved from the value
|
||||
resultValue := methodValue.Value(inputValue);
|
||||
|
||||
@@ -692,18 +694,11 @@ begin
|
||||
Assert.IsTrue(TypeInfo(TDataMethodProc) = tv.TypeInfo, 'TValue should hold TMethodProc type info');
|
||||
|
||||
// --- 6. Test Validation and Error Handling ---
|
||||
// Test creating a value with a nil type
|
||||
Assert.WillRaise(
|
||||
procedure begin TDataType.FromMethod(nil, myFunc); end,
|
||||
EArgumentException,
|
||||
'FromMethod with nil type should raise an exception'
|
||||
);
|
||||
|
||||
// Test creating a value with a nil function
|
||||
Assert.WillRaise(
|
||||
procedure begin TDataType.FromMethod(methodType1, nil); end,
|
||||
procedure begin methodType1.CreateValue(nil); end,
|
||||
EArgumentException,
|
||||
'FromMethod with nil function should raise an exception'
|
||||
'CreateValue with nil function should raise an exception'
|
||||
);
|
||||
end;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user