Skip to content

Commit

Permalink
Merge pull request #102 from ballerina-platform/add-digits-constraint
Browse files Browse the repository at this point in the history
Add constraint support for number of digits
  • Loading branch information
TharmiganK authored Oct 27, 2023
2 parents 4b09a00 + af9e9ef commit 8ec0020
Show file tree
Hide file tree
Showing 28 changed files with 1,010 additions and 66 deletions.
6 changes: 3 additions & 3 deletions ballerina/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
org = "ballerina"
name = "constraint"
version = "1.4.1"
version = "1.5.0"
authors = ["Ballerina"]
keywords = ["constraint", "validation"]
repository = "https://github.com/ballerina-platform/module-ballerina-constraint"
Expand All @@ -15,5 +15,5 @@ graalvmCompatible = true
[[platform.java17.dependency]]
groupId = "io.ballerina.stdlib"
artifactId = "constraint-native"
version = "1.4.1"
path = "../native/build/libs/constraint-native-1.4.1-SNAPSHOT.jar"
version = "1.5.0"
path = "../native/build/libs/constraint-native-1.5.0-SNAPSHOT.jar"
2 changes: 1 addition & 1 deletion ballerina/CompilerPlugin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ id = "constraint-compiler-plugin"
class = "io.ballerina.stdlib.constraint.compiler.ConstraintCompilerPlugin"

[[dependency]]
path = "../compiler-plugin/build/libs/constraint-compiler-plugin-1.4.1-SNAPSHOT.jar"
path = "../compiler-plugin/build/libs/constraint-compiler-plugin-1.5.0-SNAPSHOT.jar"
2 changes: 1 addition & 1 deletion ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ distribution-version = "2201.8.0"
[[package]]
org = "ballerina"
name = "constraint"
version = "1.4.1"
version = "1.5.0"
dependencies = [
{org = "ballerina", name = "jballerina.java"},
{org = "ballerina", name = "test"},
Expand Down
10 changes: 10 additions & 0 deletions ballerina/constraint.bal
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,13 @@ public type ConstraintRecord record {|
# + maxValue - The inclusive upper bound of the constrained type
# + minValueExclusive - The exclusive lower bound of the constrained type
# + maxValueExclusive - The exclusive upper bound of the constrained type
# + maxDigits - The maximum number of digits in the constrained type
public type IntConstraints record {|
int|record{| *ConstraintRecord; int value; |} minValue?;
int|record{| *ConstraintRecord; int value; |} maxValue?;
int|record{| *ConstraintRecord; int value; |} minValueExclusive?;
int|record{| *ConstraintRecord; int value; |} maxValueExclusive?;
int|record{| *ConstraintRecord; int value; |} maxDigits?;
|};

# Represents the constraints associated with `float` type.
Expand All @@ -80,11 +82,15 @@ public type IntConstraints record {|
# + maxValue - The inclusive upper bound of the constrained type
# + minValueExclusive - The exclusive lower bound of the constrained type
# + maxValueExclusive - The exclusive upper bound of the constrained type
# + maxIntegerDigits - The maximum number of digits in the integer part of the constrained type
# + maxFractionDigits - The maximum number of digits in the fraction part of the constrained type
public type FloatConstraints record {|
float|record{| *ConstraintRecord; float value; |} minValue?;
float|record{| *ConstraintRecord; float value; |} maxValue?;
float|record{| *ConstraintRecord; float value; |} minValueExclusive?;
float|record{| *ConstraintRecord; float value; |} maxValueExclusive?;
int|record{| *ConstraintRecord; int value; |} maxIntegerDigits?;
int|record{| *ConstraintRecord; int value; |} maxFractionDigits?;
|};

# Represents the constraints associated with `int`, `float` and `decimal` types.
Expand All @@ -93,11 +99,15 @@ public type FloatConstraints record {|
# + maxValue - The inclusive upper bound of the constrained type
# + minValueExclusive - The exclusive lower bound of the constrained type
# + maxValueExclusive - The exclusive upper bound of the constrained type
# + maxIntegerDigits - The maximum number of digits in the integer part of the constrained type
# + maxFractionDigits - The maximum number of digits in the fraction part of the constrained type
public type NumberConstraints record {|
decimal|record{| *ConstraintRecord; decimal value; |} minValue?;
decimal|record{| *ConstraintRecord; decimal value; |} maxValue?;
decimal|record{| *ConstraintRecord; decimal value; |} minValueExclusive?;
decimal|record{| *ConstraintRecord; decimal value; |} maxValueExclusive?;
int|record{| *ConstraintRecord; int value; |} maxIntegerDigits?;
int|record{| *ConstraintRecord; int value; |} maxFractionDigits?;
|};

# Represents the constraints associated with `string` type.
Expand Down
253 changes: 253 additions & 0 deletions ballerina/tests/float_constraint_on_type_test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,256 @@ isolated function testFloatConstraintOnTypeFailure2() {
test:assertFail("Expected error not found.");
}
}

@Float {
maxIntegerDigits: 5,
maxFractionDigits: 4
}
type MaxDigitFloatType float;

@test:Config {}
function testMaxDigitFloatPositive() {
MaxDigitFloatType|error validation = validate(12934.8065);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 12934.8065);
}

validation = validate(12.80);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 12.80);
}

validation = validate(0.0);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 0.0);
}

validation = validate(-12934.8065);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, -12934.8065);
}

validation = validate(-12.80);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, -12.80);
}

validation = validate(-0.0);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, -0.0);
}

validation = validate(1234);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 1234.0);
}

validation = validate(1234.00000000);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 1234.0);
}

validation = validate(0.0001);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 0.0001);
}

validation = validate(-0.0001);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, -0.0001);
}

validation = validate(0);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 0.0);
}

validation = validate(+1234.456);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 1234.456);
}

validation = validate(1.2345e3);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 1234.5);
}

validation = validate(1.2345e+3);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 1234.5);
}

validation = validate(101234.2e-3);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 101.2342);
}

validation = validate(.2345);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 0.2345);
}
}

@test:Config {}
function testMaxDigitFloatNegative() {
MaxDigitFloatType|error validation = validate(1234567.435);
if validation is error {
test:assertEquals(validation.message(), "Validation failed for '$:maxIntegerDigits' constraint(s).");
} else {
test:assertFail("Expected error not found.");
}

validation = validate(1234.12345);
if validation is error {
test:assertEquals(validation.message(), "Validation failed for '$:maxFractionDigits' constraint(s).");
} else {
test:assertFail("Expected error not found.");
}

validation = validate(1234567.12345);
if validation is error {
test:assertEquals(validation.message(), "Validation failed for '$:maxFractionDigits','$:maxIntegerDigits' constraint(s).");
} else {
test:assertFail("Expected error not found.");
}

validation = validate(0.00001);
if validation is error {
test:assertEquals(validation.message(), "Validation failed for '$:maxFractionDigits' constraint(s).");
} else {
test:assertFail("Expected error not found.");
}

validation = validate(-0.00001);
if validation is error {
test:assertEquals(validation.message(), "Validation failed for '$:maxFractionDigits' constraint(s).");
} else {
test:assertFail("Expected error not found.");
}

validation = validate(1.23e6);
if validation is error {
test:assertEquals(validation.message(), "Validation failed for '$:maxIntegerDigits' constraint(s).");
} else {
test:assertFail("Expected error not found.");
}

validation = validate(1.234e-6);
if validation is error {
test:assertEquals(validation.message(), "Validation failed for '$:maxFractionDigits' constraint(s).");
} else {
test:assertFail("Expected error not found.");
}

validation = validate(.123456);
if validation is error {
test:assertEquals(validation.message(), "Validation failed for '$:maxFractionDigits' constraint(s).");
} else {
test:assertFail("Expected error not found.");
}
}

type DigitFloat float;

@Float {
maxIntegerDigits: {
value: 4,
message: "Integer digits should be less than or equal to 4"
}
}
type MaxIntegerDigitFloatRefType DigitFloat;

@test:Config {}
function testMaxIntegerDigitsRefType() {
MaxIntegerDigitFloatRefType|error validation = validate(-1234.12345);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, -1234.12345);
}

validation = validate(12.1234000);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 12.1234);
}

validation = validate(123456);
if validation is error {
test:assertEquals(validation.message(), "Integer digits should be less than or equal to 4.");
} else {
test:assertFail("Expected error not found.");
}

validation = validate(1234456.001);
if validation is error {
test:assertEquals(validation.message(), "Integer digits should be less than or equal to 4.");
} else {
test:assertFail("Expected error not found.");
}
}

@Float {
maxFractionDigits: {
value: 3,
message: "Fraction digits should be less than or equal to 3"
}
}
type MaxFractionDigitFloatRefType DigitFloat;

@test:Config {}
function testMaxFractionDigitsRefType() {
MaxFractionDigitFloatRefType|error validation = validate(1234.12);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 1234.12);
}

validation = validate(0.001);
if validation is error {
test:assertFail("Unexpected error found.");
} else {
test:assertEquals(validation, 0.001);
}

validation = validate(1234.1234);
if validation is error {
test:assertEquals(validation.message(), "Fraction digits should be less than or equal to 3.");
} else {
test:assertFail("Expected error not found.");
}
}
Loading

0 comments on commit 8ec0020

Please sign in to comment.