Skip to content

Commit

Permalink
Fix scale precision error message when digits is calculated as negati…
Browse files Browse the repository at this point in the history
…ve (#1790)
  • Loading branch information
SatsunkevichAlex committed Aug 12, 2021
1 parent 8b0d4df commit 016b415
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 24 deletions.
43 changes: 26 additions & 17 deletions src/FluentValidation.Tests/ScalePrecisionValidatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@
#endregion

namespace FluentValidation.Tests {
using System;
using System.Globalization;
using System.Linq;
using System.Threading;
using Xunit;
using Validators;

public class ScalePrecisionValidatorTests {
public ScalePrecisionValidatorTests() {
Expand All @@ -44,6 +39,9 @@ public class ScalePrecisionValidatorTests {

result = validator.Validate(new Person { Discount = 0.34M });
result.IsValid.ShouldBeTrue();

result = validator.Validate(new Person { Discount = 0.04M });
result.IsValid.ShouldBeTrue();
}

[Fact]
Expand All @@ -66,7 +64,6 @@ public class ScalePrecisionValidatorTests {
result.IsValid.ShouldBeTrue();
}


[Fact]
public void Scale_precision_should_not_be_valid() {
var validator = new TestValidator(v => v.RuleFor(x => x.Discount).ScalePrecision(2, 4));
Expand All @@ -90,6 +87,14 @@ public class ScalePrecisionValidatorTests {
result = validator.Validate(new Person { Discount = 65.430M });
result.IsValid.ShouldBeFalse();
result.Errors[0].ErrorMessage.ShouldEqual("'Discount' must not be more than 4 digits in total, with allowance for 2 decimals. 2 digits and 3 decimals were found.");

result = validator.Validate(new Person { Discount = 0.003M });
result.IsValid.ShouldBeFalse();
result.Errors[0].ErrorMessage.ShouldEqual("'Discount' must not be more than 4 digits in total, with allowance for 2 decimals. 0 digits and 3 decimals were found.");

result = validator.Validate(new Person { Discount = 0.030303M });
result.IsValid.ShouldBeFalse();
result.Errors[0].ErrorMessage.ShouldEqual("'Discount' must not be more than 4 digits in total, with allowance for 2 decimals. 0 digits and 6 decimals were found.");
}

[Fact]
Expand Down Expand Up @@ -146,6 +151,10 @@ public class ScalePrecisionValidatorTests {
result.IsValid.ShouldBeFalse();
result.Errors[0].ErrorMessage.ShouldEqual("'Discount' must not be more than 2 digits in total, with allowance for 2 decimals. 0 digits and 3 decimals were found.");

result = validator.Validate(new Person { Discount = 0.041M });
result.IsValid.ShouldBeFalse();
result.Errors[0].ErrorMessage.ShouldEqual("'Discount' must not be more than 2 digits in total, with allowance for 2 decimals. 0 digits and 3 decimals were found.");

result = validator.Validate(new Person { Discount = 1.34M });
result.IsValid.ShouldBeFalse();
result.Errors[0].ErrorMessage.ShouldEqual("'Discount' must not be more than 2 digits in total, with allowance for 2 decimals. 1 digits and 2 decimals were found.");
Expand All @@ -169,17 +178,17 @@ public class ScalePrecisionValidatorTests {
result.IsValid.ShouldBeTrue();
}

[Fact]
public void Scale_precision_should_not_be_valid_when_ignoring_trailing_zeroes() {
var validator = new TestValidator(v => v.RuleFor(x => x.Discount).ScalePrecision(2, 4, true));
[Fact]
public void Scale_precision_should_not_be_valid_when_ignoring_trailing_zeroes() {
var validator = new TestValidator(v => v.RuleFor(x => x.Discount).ScalePrecision(2, 4, true));

var result = validator.Validate(new Person { Discount = 1565.0M });
result.IsValid.ShouldBeFalse();
result.Errors[0].ErrorMessage.ShouldEqual("'Discount' must not be more than 4 digits in total, with allowance for 2 decimals. 4 digits and 0 decimals were found.");
var result = validator.Validate(new Person { Discount = 1565.0M });
result.IsValid.ShouldBeFalse();
result.Errors[0].ErrorMessage.ShouldEqual("'Discount' must not be more than 4 digits in total, with allowance for 2 decimals. 4 digits and 0 decimals were found.");

result = validator.Validate(new Person { Discount = 15.0000000000000000000000001M });
result.IsValid.ShouldBeFalse();
result.Errors[0].ErrorMessage.ShouldEqual("'Discount' must not be more than 4 digits in total, with allowance for 2 decimals. 2 digits and 25 decimals were found.");
}
}
result = validator.Validate(new Person { Discount = 15.0000000000000000000000001M });
result.IsValid.ShouldBeFalse();
result.Errors[0].ErrorMessage.ShouldEqual("'Discount' must not be more than 4 digits in total, with allowance for 2 decimals. 2 digits and 25 decimals were found.");
}
}
}
13 changes: 6 additions & 7 deletions src/FluentValidation/Validators/ScalePrecisionValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

namespace FluentValidation.Validators {
using System;
using Resources;

// Attribution: This class was contributed to FluentValidation using code posted on StackOverflow by Jon Skeet
// The original code can be found at https://stackoverflow.com/a/764102
Expand Down Expand Up @@ -58,7 +57,7 @@ public class ScalePrecisionValidator<T> : PropertyValidator<T, decimal> {
context.MessageFormatter
.AppendArgument("ExpectedPrecision", Precision)
.AppendArgument("ExpectedScale", Scale)
.AppendArgument("Digits", actualIntegerDigits)
.AppendArgument("Digits", actualIntegerDigits < 0 ? 0 : actualIntegerDigits)
.AppendArgument("ActualScale", scale);

return false;
Expand All @@ -85,7 +84,7 @@ public class ScalePrecisionValidator<T> : PropertyValidator<T, decimal> {
private static UInt32[] GetBits(decimal Decimal) {
// We want the integer parts as uint
// C# doesn't permit int[] to uint[] conversion, but .NET does. This is somewhat evil...
return (uint[]) (object) decimal.GetBits(Decimal);
return (uint[])(object)decimal.GetBits(Decimal);
}

private static decimal GetMantissa(decimal Decimal) {
Expand All @@ -102,10 +101,10 @@ public class ScalePrecisionValidator<T> : PropertyValidator<T, decimal> {
private int GetScale(decimal Decimal) {
uint scale = GetUnsignedScale(Decimal);
if (IgnoreTrailingZeros) {
return (int) (scale - NumTrailingZeros(Decimal));
return (int)(scale - NumTrailingZeros(Decimal));
}

return (int) scale;
return (int)scale;
}

private static uint NumTrailingZeros(decimal Decimal) {
Expand All @@ -126,10 +125,10 @@ public class ScalePrecisionValidator<T> : PropertyValidator<T, decimal> {
}

if (IgnoreTrailingZeros) {
return (int) (precision - NumTrailingZeros(Decimal));
return (int)(precision - NumTrailingZeros(Decimal));
}

return (int) precision;
return (int)precision;
}

protected override string GetDefaultMessageTemplate(string errorCode) {
Expand Down

0 comments on commit 016b415

Please sign in to comment.