diff --git a/Flagsmith.Engine/Engine.cs b/Flagsmith.Engine/Engine.cs index f2567bb..4d7fb6a 100644 --- a/Flagsmith.Engine/Engine.cs +++ b/Flagsmith.Engine/Engine.cs @@ -358,7 +358,7 @@ private static bool MatchingFunctionName(object contextValue, Condition conditio switch (contextValue.GetType().FullName) { case "System.Int32": - return IntOperations((Int32)contextValue, condition); + return LongOperations((Int32)contextValue, condition); case "System.Int64": return LongOperations((Int64)contextValue, condition); case "System.Double": @@ -411,30 +411,25 @@ private static bool LongOperations(long contextValue, Condition condition) } } - private static bool IntOperations(long contextValue, Condition condition) + private static bool DoubleOperations(double contextValue, Condition condition) { - switch (condition.Operator) + double conditionValue; + try { - case Operator.Equal: return contextValue == InvariantConvert.ToInt32(condition.Value.String); - case Operator.NotEqual: return contextValue != InvariantConvert.ToInt32(condition.Value.String); - case Operator.GreaterThan: return contextValue > InvariantConvert.ToInt32(condition.Value.String); - case Operator.GreaterThanInclusive: return contextValue >= InvariantConvert.ToInt32(condition.Value.String); - case Operator.LessThan: return contextValue < InvariantConvert.ToInt32(condition.Value.String); - case Operator.LessThanInclusive: return contextValue <= InvariantConvert.ToInt32(condition.Value.String); - default: throw new ArgumentException("Invalid Operator"); + conditionValue = InvariantConvert.ToDouble(condition.Value.String); + } + catch (FormatException) + { + return false; } - } - - private static bool DoubleOperations(double contextValue, Condition condition) - { switch (condition.Operator) { - case Operator.Equal: return contextValue == InvariantConvert.ToDouble(condition.Value.String); - case Operator.NotEqual: return contextValue != InvariantConvert.ToDouble(condition.Value.String); - case Operator.GreaterThan: return contextValue > InvariantConvert.ToDouble(condition.Value.String); - case Operator.GreaterThanInclusive: return contextValue >= InvariantConvert.ToDouble(condition.Value.String); - case Operator.LessThan: return contextValue < InvariantConvert.ToDouble(condition.Value.String); - case Operator.LessThanInclusive: return contextValue <= InvariantConvert.ToDouble(condition.Value.String); + case Operator.Equal: return contextValue == conditionValue; + case Operator.NotEqual: return contextValue != conditionValue; + case Operator.GreaterThan: return contextValue > conditionValue; + case Operator.GreaterThanInclusive: return contextValue >= conditionValue; + case Operator.LessThan: return contextValue < conditionValue; + case Operator.LessThanInclusive: return contextValue <= conditionValue; default: throw new ArgumentException("Invalid Operator"); } } diff --git a/Flagsmith.Engine/Utils/InvariantConvert.cs b/Flagsmith.Engine/Utils/InvariantConvert.cs index 881aa71..3da009a 100644 --- a/Flagsmith.Engine/Utils/InvariantConvert.cs +++ b/Flagsmith.Engine/Utils/InvariantConvert.cs @@ -12,15 +12,6 @@ namespace FlagsmithEngine.Utils /// internal static class InvariantConvert { - /// - /// Converts the string representation of a number to its 32-bit signed integer equivalent - /// using culture-invariant formatting. - /// - /// A string containing a number to convert. - /// A 32-bit signed integer equivalent to the number in value. - public static int ToInt32(string value) => - Convert.ToInt32(value, CultureInfo.InvariantCulture); - /// /// Converts the string representation of a number to its 64-bit signed integer equivalent /// using culture-invariant formatting. diff --git a/Flagsmith.EngineTest/EngineTest.cs b/Flagsmith.EngineTest/EngineTest.cs index 15543fd..f120af8 100644 --- a/Flagsmith.EngineTest/EngineTest.cs +++ b/Flagsmith.EngineTest/EngineTest.cs @@ -63,6 +63,53 @@ public static IEnumerable ExtractTestCaseFilenames() return testCases; } + [Theory] + [InlineData(95, Operator.GreaterThan, "90.5")] + [InlineData(95, Operator.NotEqual, "90.5")] + [InlineData(1, Operator.Equal, "not_an_int")] + [InlineData(1.5, Operator.LessThan, "not_a_number")] + public void TestGetEvaluationResult_ShouldNotMatchSegment_WhenConditionValueIsNotOfNumericTraitType(object traitValue, Operator conditionOperator, string conditionValue) + { + // Given + var context = new EvaluationContext + { + Environment = new EnvironmentContext { Key = "test-env", Name = "Test Environment" }, + Identity = new IdentityContext + { + Identifier = "user-123", + Traits = new Dictionary { { "score", traitValue } }, + }, + Features = new Dictionary>(), + Segments = new Dictionary> + { + { + "1", new SegmentContext + { + Key = "1", + Name = "high_scorers", + Rules = new[] + { + new SegmentRule + { + Type = TypeEnum.All, + Conditions = new[] + { + new Condition { Operator = conditionOperator, Property = "score", Value = conditionValue }, + }, + }, + }, + } + }, + }, + }; + + // When + var result = new Engine().GetEvaluationResult(context); + + // Then + Assert.Empty(result.Segments); + } + [Fact] public void TestGetEvaluationResult_ShouldNotMutateOriginalContextIdentity() {