Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rules using Operators.In are not working properly with InMemory RulesFramework #54

Closed
isabelneto opened this issue Jan 7, 2022 · 0 comments
Assignees
Labels
bug Something isn't working

Comments

@isabelneto
Copy link
Contributor

isabelneto commented Jan 7, 2022

Description:

When we try to create a rule using Operand.In the list sent in SetOperand is not being correctly evaluated. The problem seems to be in the Rules.Framework.Providers.InMemory.RuleFactory<TContentType, TConditionType>.CreateValueConditionNode method which, in case the DataType is DataTypes.String, is not considering the possibility that the conditionNodeDataModel.Operand can be an Enumerable:

        private static IConditionNode<TConditionType> CreateValueConditionNode(IConditionNodeBuilder<TConditionType> conditionNodeBuilder, ValueConditionNodeDataModel<TConditionType> conditionNodeDataModel)
        {
            return conditionNodeDataModel.DataType switch
            {
                DataTypes.Integer => conditionNodeBuilder.AsValued(conditionNodeDataModel.ConditionType)
                    .OfDataType<int>()
                    .WithComparisonOperator(conditionNodeDataModel.Operator)
                    .SetOperand(Convert.ToInt32(conditionNodeDataModel.Operand, CultureInfo.InvariantCulture))
                    .Build(),
                DataTypes.Decimal => conditionNodeBuilder.AsValued(conditionNodeDataModel.ConditionType)
                   .OfDataType<decimal>()
                   .WithComparisonOperator(conditionNodeDataModel.Operator)
                   .SetOperand(Convert.ToDecimal(conditionNodeDataModel.Operand, CultureInfo.InvariantCulture))
                   .Build(),
                DataTypes.String => conditionNodeBuilder.AsValued(conditionNodeDataModel.ConditionType)
                   .OfDataType<string>()
                   .WithComparisonOperator(conditionNodeDataModel.Operator)
                   .SetOperand(Convert.ToString(conditionNodeDataModel.Operand, CultureInfo.InvariantCulture))
                   .Build(),
                DataTypes.Boolean => conditionNodeBuilder.AsValued(conditionNodeDataModel.ConditionType)
                   .OfDataType<bool>()
                   .WithComparisonOperator(conditionNodeDataModel.Operator)
                   .SetOperand(Convert.ToBoolean(conditionNodeDataModel.Operand, CultureInfo.InvariantCulture))
                    .Build(),
                _ => throw new NotSupportedException($"Unsupported data type: {conditionNodeDataModel.DataType}."),
            };
        }

OS:

Windows 10

.Net SDK:

.Net Standard 2.1

Exception message and stack trace:

"System.NotSupportedException: The combination 'one-to-one-In' is not supported.
at Rules.Framework.Evaluation.ValueEvaluation.Dispatchers.ConditionEvalDispatchProvider.ThrowIfUnsupportedOperandsAndOperatorCombination(String combination) in C:\\_git\\rules-framework\\src\\Rules.Framework\\Evaluation\\ValueEvaluation\\Dispatchers\\ConditionEvalDispatchProvider.cs:line 71
at Rules.Framework.Evaluation.ValueEvaluation.Dispatchers.ConditionEvalDispatchProvider.GetEvalDispatcher(Object leftOperand, Operators operator, Object rightOperand) in C:\\_git\\rules-framework\\src\\Rules.Framework\\Evaluation\\ValueEvaluation\\Dispatchers\\ConditionEvalDispatchProvider.cs:line 55
at Rules.Framework.Evaluation.ValueEvaluation.DeferredEval.Eval[TConditionType](IEnumerable`1 conditions, IValueConditionNode`1 valueConditionNode, Object rightOperand, MatchModes matchMode) in C:\\_git\\rules-framework\\src\\Rules.Framework\\Evaluation\\ValueEvaluation\\DeferredEval.cs:line 64
at Rules.Framework.Evaluation.ValueEvaluation.DeferredEval.Eval[TConditionType](IEnumerable`1 conditions, ValueConditionNode`1 valueConditionNode, MatchModes matchMode) in C:\\_git\\rules-framework\\src\\Rules.Framework\\Evaluation\\ValueEvaluation\\DeferredEval.cs:line 42
at Rules.Framework.Evaluation.ValueEvaluation.DeferredEval.<>c__DisplayClass3_1`1.<GetDeferredEvalFor>b__4(IEnumerable`1 conditions) in C:\\_git\\rules-framework\\src\\Rules.Framework\\Evaluation\\ValueEvaluation\\DeferredEval.cs:line 30
at Rules.Framework.Evaluation.Specification.FuncSpecification`1.IsSatisfiedBy(T input) in C:\\_git\\rules-framework\\src\\Rules.Framework\\Evaluation\\Specification\\FuncSpecification.cs:line 14
at Rules.Framework.Evaluation.ConditionsEvalEngine`1.Eval(IConditionNode`1 conditionNode, IEnumerable`1 conditions, EvaluationOptions evaluationOptions) in C:\\_git\\rules-framework\\src\\Rules.Framework\\Evaluation\\ConditionsEvalEngine.cs:line 29
at Rules.Framework.RulesEngine`2.<>c__DisplayClass10_0.<MatchAsync>b__0(Rule`2 r) in C:\\_git\\rules-framework\\src\\Rules.Framework\\RulesEngine.cs:line 272
at System.Linq.Enumerable.WhereListIterator`1.ToList()
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Rules.Framework.RulesEngine`2.MatchAsync(TContentType contentType, DateTime matchDateBegin, DateTime matchDateEnd, IEnumerable`1 conditions, EvaluationOptions evaluationOptions) in C:\\_git\\rules-framework\\src\\Rules.Framework\\RulesEngine.cs:line 271
at Rules.Framework.RulesEngine`2.MatchOneAsync(TContentType contentType, DateTime matchDateTime, IEnumerable`1 conditions) in C:\\_git\\rules-framework\\src\\Rules.Framework\\RulesEngine.cs:line 109
[...]"

A repro of the issue:

this.Add(
    this.Add(
        RuleBuilder
            .NewRule<RuleContentType, ConditionType>()
            .WithName("Some Rule")
            .WithContent(
                RuleContentType.SomeContentType,
                  "SomeText"
            )
            .WithCondition(x => x
                .AsValued(ConditionType.SomeConditionType).OfDataType<string>()
                .WithComparisonOperator(Operators.In)
                .SetOperand(new[] { "11111", "22222", "33333", "44444", "55555" })
                .Build()
            )
            .WithDateBegin(DateTime.Parse("2022-01-01"))
            .Build(),
        RuleAddPriorityOption.ByPriorityNumber(1)
    );

Branch with the unit test reproducing the problem
https://github.com/Farfetch/rules-framework/tree/test/inmemory_problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

No branches or pull requests

10 participants