From a71692f5da18ae884e7c0a8d6414f32d9ded7e77 Mon Sep 17 00:00:00 2001 From: YogeshPraj Date: Mon, 12 Oct 2020 20:59:51 +0530 Subject: [PATCH] Added option to throw error on expression compilation failure (#57) --- CHANGELOG.md | 3 ++ .../ExpressionBuilders/LambdaExpressionBuilder.cs | 2 ++ src/RulesEngine/RulesEngine/Models/ReSettings.cs | 1 + src/RulesEngine/RulesEngine/RulesEngine.csproj | 2 +- src/RulesEngine/global.json | 4 ++- .../RulesEngine.UnitTest/BusinessRuleEngineTest.cs | 40 ++++++++++++++++++++-- .../RulesEngine.UnitTest.csproj | 3 ++ test/RulesEngine.UnitTest/TestData/rules9.json | 21 ++++++++++++ 8 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 test/RulesEngine.UnitTest/TestData/rules9.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c35cea..fa5be6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # CHANGELOG All notable changes to this project will be documented in this file. +## [2.1.3] - 12-10-2020 +- Optional parameter for rethrow exception on failure of expression compilation. + ## [2.1.2] - 02-10-2020 - Fixed binary expression requirement. Now any expression will work as long as it evalutes to boolean. diff --git a/src/RulesEngine/RulesEngine/ExpressionBuilders/LambdaExpressionBuilder.cs b/src/RulesEngine/RulesEngine/ExpressionBuilders/LambdaExpressionBuilder.cs index 353792b..20e7940 100644 --- a/src/RulesEngine/RulesEngine/ExpressionBuilders/LambdaExpressionBuilder.cs +++ b/src/RulesEngine/RulesEngine/ExpressionBuilders/LambdaExpressionBuilder.cs @@ -38,6 +38,8 @@ namespace RulesEngine.ExpressionBuilders } catch (Exception ex) { + if (!_reSettings.EnableExceptionAsErrorMessage) throw; + var binaryExpression = Expression.And(Expression.Constant(true), Expression.Constant(false)); var exceptionMessage = ex.Message; return Helpers.ToResultTreeExpression(rule, null, binaryExpression, typeParamExpressions, ruleInputExp, exceptionMessage); diff --git a/src/RulesEngine/RulesEngine/Models/ReSettings.cs b/src/RulesEngine/RulesEngine/Models/ReSettings.cs index 33c9449..b1426be 100644 --- a/src/RulesEngine/RulesEngine/Models/ReSettings.cs +++ b/src/RulesEngine/RulesEngine/Models/ReSettings.cs @@ -9,6 +9,7 @@ namespace RulesEngine.Models [ExcludeFromCodeCoverage] public class ReSettings { + public bool EnableExceptionAsErrorMessage { get; set; } = true; public Type[] CustomTypes { get; set; } } } diff --git a/src/RulesEngine/RulesEngine/RulesEngine.csproj b/src/RulesEngine/RulesEngine/RulesEngine.csproj index 6ba1ebf..050e78e 100644 --- a/src/RulesEngine/RulesEngine/RulesEngine.csproj +++ b/src/RulesEngine/RulesEngine/RulesEngine.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 2.1.2 + 2.1.3 Copyright (c) Microsoft Corporation. LICENSE https://github.com/microsoft/RulesEngine diff --git a/src/RulesEngine/global.json b/src/RulesEngine/global.json index c120c81..d36fe28 100644 --- a/src/RulesEngine/global.json +++ b/src/RulesEngine/global.json @@ -1,5 +1,7 @@ { "sdk": { - "version": "3.1.301" + "version": "3.1", + "rollForward": "latestFeature", + "allowPrerelease": false } } \ No newline at end of file diff --git a/test/RulesEngine.UnitTest/BusinessRuleEngineTest.cs b/test/RulesEngine.UnitTest/BusinessRuleEngineTest.cs index 85fcda6..7d8653c 100644 --- a/test/RulesEngine.UnitTest/BusinessRuleEngineTest.cs +++ b/test/RulesEngine.UnitTest/BusinessRuleEngineTest.cs @@ -306,13 +306,49 @@ namespace RulesEngine.UnitTest Assert.All(result, c => Assert.False(c.IsSuccess)); } + [Theory] + [InlineData("rules9.json")] + public void ExecuteRule_MissingMethodInExpression_ReturnsException(string ruleFileName) + { + var re = GetRulesEngine(ruleFileName, new ReSettings() { EnableExceptionAsErrorMessage = false }); + + dynamic input1 = new ExpandoObject(); + input1.Data = new { TestProperty = "" }; + input1.Boolean = false; + + var utils = new TestInstanceUtils(); + + Assert.Throws(()=> + { + List result = re.ExecuteRule("inputWorkflow", new RuleParameter("input1", input1)); + }); + } + + [Theory] + [InlineData("rules9.json")] + public void ExecuteRule_MissingMethodInExpression_DefaultParameter(string ruleFileName) + { + var re = GetRulesEngine(ruleFileName); + + dynamic input1 = new ExpandoObject(); + input1.Data = new { TestProperty = "" }; + input1.Boolean = false; + + var utils = new TestInstanceUtils(); + + List result = re.ExecuteRule("inputWorkflow", new RuleParameter("input1", input1)); + Assert.NotNull(result); + Assert.IsType>(result); + Assert.All(result, c => Assert.False(c.IsSuccess)); + } + private RulesEngine CreateRulesEngine(WorkflowRules workflow) { var json = JsonConvert.SerializeObject(workflow); return new RulesEngine(new string[] { json }, null); } - private RulesEngine GetRulesEngine(string filename) + private RulesEngine GetRulesEngine(string filename, ReSettings reSettings = null) { var filePath = Path.Combine(Directory.GetCurrentDirectory() as string, "TestData", filename); var data = File.ReadAllText(filePath); @@ -325,7 +361,7 @@ namespace RulesEngine.UnitTest var injectWorkflowStr = JsonConvert.SerializeObject(injectWorkflow); var mockLogger = new Mock(); - return new RulesEngine(new string[] { data, injectWorkflowStr }, mockLogger.Object); + return new RulesEngine(new string[] { data, injectWorkflowStr }, mockLogger.Object, reSettings); } private dynamic GetInput1() diff --git a/test/RulesEngine.UnitTest/RulesEngine.UnitTest.csproj b/test/RulesEngine.UnitTest/RulesEngine.UnitTest.csproj index fbca9a3..3c83e7f 100644 --- a/test/RulesEngine.UnitTest/RulesEngine.UnitTest.csproj +++ b/test/RulesEngine.UnitTest/RulesEngine.UnitTest.csproj @@ -33,6 +33,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/test/RulesEngine.UnitTest/TestData/rules9.json b/test/RulesEngine.UnitTest/TestData/rules9.json new file mode 100644 index 0000000..4042953 --- /dev/null +++ b/test/RulesEngine.UnitTest/TestData/rules9.json @@ -0,0 +1,21 @@ +{ + "WorkflowName": "inputWorkflow", + "Rules": [ + { + "RuleName": "GiveDiscount10", + "SuccessEvent": "10", + "ErrorMessage": "One or more adjust rules failed.", + "ErrorType": "Error", + "RuleExpressionType": "LambdaExpression", + "Expression": "input1.Boolean" + }, + { + "RuleName": "GiveDiscount20", + "SuccessEvent": "20", + "ErrorMessage": "One or more adjust rules failed.", + "ErrorType": "Error", + "RuleExpressionType": "LambdaExpression", + "Expression": "input1.Boolean && input1.Data.NotExistingMethod()" + } + ] +} \ No newline at end of file