Abbasc52/linux behaviour test (#512)

* Added testcase as per bug

* fixed test case

* Added tests from bugs

* fixed version for FastExpressionCompiler

* updated changelog and added readme file in nuget
pull/516/head v5.0.2
Abbas Cyclewala 2023-08-16 08:53:08 +05:30 committed by GitHub
parent b9e1ece812
commit 9e7918dde2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 405 additions and 5 deletions

View File

@ -2,6 +2,9 @@
All notable changes to this project will be documented in this file.
## [5.0.2]
- Fixed Scoped Params returning incorrect results in some corner case scenarios
## [5.0.1]
- Added option to disable automatic type registry for input parameters in reSettings
- Added option to make expression case sensitive in reSettings

View File

@ -2,14 +2,15 @@
<PropertyGroup>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<Version>5.0.1</Version>
<Version>5.0.2</Version>
<Copyright>Copyright (c) Microsoft Corporation.</Copyright>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageProjectUrl>https://github.com/microsoft/RulesEngine</PackageProjectUrl>
<Authors>Abbas Cyclewala</Authors>
<Description>Rules Engine is a package for abstracting business logic/rules/policies out of the system. This works in a very simple way by giving you an ability to put your rules in a store outside the core logic of the system thus ensuring that any change in rules doesn't affect the core system.</Description>
<PackageReleaseNotes>https://github.com/microsoft/RulesEngine/blob/main/CHANGELOG.md</PackageReleaseNotes>
<PackageTags>BRE, Rules Engine, Abstraction</PackageTags>
<PackageReleaseNotes>https://github.com/microsoft/RulesEngine/blob/main/CHANGELOG.md</PackageReleaseNotes>
<PackageTags>BRE, Rules Engine, Abstraction</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
@ -27,11 +28,12 @@
</PropertyGroup>
<ItemGroup>
<None Include="..\..\LICENSE" Pack="true" PackagePath="" />
<None Include="..\..\LICENSE" Pack="true" PackagePath="\" />
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FastExpressionCompiler" Version="3.3.4" />
<PackageReference Include="FastExpressionCompiler" Version="[3.3.3]" />
<PackageReference Include="FluentValidation" Version="11.5.2" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />

View File

@ -532,6 +532,280 @@ namespace RulesEngine.UnitTest
Assert.All(result, c => Assert.True(c.IsSuccess));
}
[Theory]
[InlineData("rules11.json")]
public async Task RulesEngineWithGlobalParam_RunsSuccessfully(string ruleFileName)
{
var re = GetRulesEngine(ruleFileName, new ReSettings() { });
var input1 = new[] {
new {
Value= 0.13259286,
ChangeDateTime= "2023-07-28T19:57:07.432339Z"
},
new {
Value= 0.09435427,
ChangeDateTime= "2023-07-28T19:58:04.536459Z"
},
new {
Value= 0.14896593,
ChangeDateTime= "2023-07-28T19:59:08.682072Z"
},
new {
Value= 0.12852388,
ChangeDateTime= "2023-07-28T20:00:06.78036Z"
},
new {
Value= 0.17011189,
ChangeDateTime= "2023-07-28T20:00:54.873615Z"
},
new {
Value= 0.0532116,
ChangeDateTime= "2023-07-28T20:02:52.04049Z"
},
new {
Value= 0.04064374,
ChangeDateTime= "2023-07-28T20:03:54.168499Z"
},
new {
Value= 0.03748944,
ChangeDateTime= "2023-07-28T20:03:54.194786Z"
},
new {
Value= 0.07752395,
ChangeDateTime= "2023-07-28T20:06:32.451464Z"
},
new {
Value= 0.07294922,
ChangeDateTime= "2023-07-28T20:07:38.691755Z"
},
new {
Value= 0.09892442,
ChangeDateTime= "2023-07-28T20:08:37.98802Z"
},
new {
Value= 0.06370641,
ChangeDateTime= "2023-07-28T20:05:41.358461Z"
},
new {
Value= 0.07550429,
ChangeDateTime= "2023-07-28T20:09:48.129748Z"
},
new {
Value= 0.0653021,
ChangeDateTime= "2023-07-28T20:10:48.274482Z"
},
new {
Value= 0.09304246,
ChangeDateTime= "2023-07-28T20:11:49.436983Z"
},
new {
Value= 0.0797422,
ChangeDateTime= "2023-07-28T20:12:53.609118Z"
},
new {
Value= 0.08211832,
ChangeDateTime= "2023-07-28T20:13:52.699728Z"
},
new {
Value= 0.06955433,
ChangeDateTime= "2023-07-28T20:15:03.843289Z"
},
new {
Value= 0.07626661,
ChangeDateTime= "2023-07-28T20:15:03.870057Z"
},
new {
Value= 0.05033984,
ChangeDateTime= "2023-07-28T20:16:17.032262Z"
},
new {
Value= 0.05202596,
ChangeDateTime= "2023-07-28T20:17:20.172669Z"
},
new {
Value= 0.06861198,
ChangeDateTime= "2023-07-28T20:18:32.303309Z"
},
new {
Value= 0.04935532,
ChangeDateTime= "2023-07-28T20:19:33.451426Z"
},
new {
Value= 0.04073699,
ChangeDateTime= "2023-07-28T20:20:37.737395Z"
},
new {
Value= 0.02164916,
ChangeDateTime= "2023-07-28T20:21:38.883635Z"
},
new {
Value= 0.01334031,
ChangeDateTime= "2023-07-28T20:22:40.053193Z"
},
new {
Value= 0.0336915,
ChangeDateTime= "2023-07-28T20:23:44.240297Z"
},
new {
Value= 0.04870055,
ChangeDateTime= "2023-07-28T20:26:33.584756Z"
},
new {
Value= 0.07125243,
ChangeDateTime= "2023-07-28T20:28:11.7889Z"
},
new {
Value= 0.04904275,
ChangeDateTime= "2023-07-28T20:24:40.346216Z"
},
new {
Value= 0.03625701,
ChangeDateTime= "2023-07-28T20:27:20.707478Z"
},
new {
Value= 0.05703328,
ChangeDateTime= "2023-07-28T20:28:57.876436Z"
},
new {
Value= 0.04364996,
ChangeDateTime= "2023-07-28T20:25:43.496357Z"
},
new {
Value= 0.07558272,
ChangeDateTime= "2023-07-28T20:30:11.023295Z"
},
new {
Value= 0.03073958,
ChangeDateTime= "2023-07-28T20:33:00.347672Z"
},
new {
Value= 0.0341309,
ChangeDateTime= "2023-07-28T20:33:59.790621Z"
},
new {
Value= 0.05270871,
ChangeDateTime= "2023-07-28T20:31:15.166193Z"
},
new {
Value= 0.09138862,
ChangeDateTime= "2023-07-28T20:32:08.259273Z"
},
new {
Value= 0.15922104,
ChangeDateTime= "2023-07-28T20:35:12.963809Z"
},
new {
Value= 0.11383641,
ChangeDateTime= "2023-07-28T20:36:26.120815Z"
},
new {
Value= 0.12404025,
ChangeDateTime= "2023-07-28T20:37:37.27212Z"
},
new {
Value= 0.06010197,
ChangeDateTime= "2023-07-28T20:38:47.409412Z"
},
new {
Value= 0.08396237,
ChangeDateTime= "2023-07-28T20:39:37.504217Z"
},
new {
Value= 0.06731881,
ChangeDateTime= "2023-07-28T20:40:27.588895Z"
},
new {
Value= 0.05617253,
ChangeDateTime= "2023-07-28T20:41:33.760373Z"
},
new {
Value= 0.0585155,
ChangeDateTime= "2023-07-28T20:42:26.847144Z"
},
new {
Value= 0.06793098,
ChangeDateTime= "2023-07-28T20:43:36.988904Z"
},
new {
Value= 0.06879344,
ChangeDateTime= "2023-07-28T20:44:46.133926Z"
},
new {
Value= 0.06931814,
ChangeDateTime= "2023-07-28T20:45:50.275932Z"
},
new {
Value= 0.04802603,
ChangeDateTime= "2023-07-28T20:46:36.367289Z"
},
new {
Value= 0.04036225,
ChangeDateTime= "2023-07-28T20:47:27.484188Z"
},
new {
Value= 0.04968483,
ChangeDateTime= "2023-07-28T20:48:13.582228Z"
},
new {
Value= 0.0773483,
ChangeDateTime= "2023-07-28T19:49:16.354277Z"
},
new {
Value= 0.08710921,
ChangeDateTime= "2023-07-28T19:48:25.253743Z"
},
new {
Value= 0.07665287,
ChangeDateTime= "2023-07-28T19:50:25.496642Z"
},
new {
Value= 0.06121748,
ChangeDateTime= "2023-07-28T19:51:20.644955Z"
},
new {
Value= 0.04179136,
ChangeDateTime= "2023-07-28T19:52:26.793369Z"
},
new {
Value= 0.13522345,
ChangeDateTime= "2023-07-28T19:54:19.051669Z"
},
new {
Value= 0.08536856,
ChangeDateTime= "2023-07-28T19:56:04.287806Z"
},
new {
Value= 0.05041369,
ChangeDateTime= "2023-07-28T19:53:18.901696Z"
},
new {
Value= 0.1627249,
ChangeDateTime= "2023-07-28T19:55:13.160235Z"
},
new {
Value= 0.05,
ChangeDateTime= "2023-07-28T19:54:03.2197Z"
},
new {
Value= 0.05,
ChangeDateTime= "2023-07-28T19:56:00.802023Z"
},
new {
Value= 0.02792705297470093,
ChangeDateTime= "2023-07-28T20:49:03.6825337Z"
}
}.ToList();
var result = await re.ExecuteAllRulesAsync("MyWorkflow", new RuleParameter("input1", input1));
Assert.NotNull(result);
Assert.False(result[0].IsSuccess);
Assert.True(result[1].IsSuccess);
}
[Fact]
public async Task ExecuteRule_RuntimeError_ShouldReturnAsErrorMessage()
@ -768,6 +1042,10 @@ namespace RulesEngine.UnitTest
Assert.False(re.ContainsWorkflow(NotExistedWorkflowName));
}
[Theory]
[InlineData(typeof(RulesEngine), typeof(IRulesEngine))]
public void Class_PublicMethods_ArePartOfInterface(Type classType, Type interfaceType)

View File

@ -27,6 +27,9 @@
<None Update="TestData\rules1.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="TestData\rules11.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="TestData\rules4.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

View File

@ -2,6 +2,7 @@
// Licensed under the MIT License.
using RulesEngine.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
@ -10,6 +11,14 @@ using Xunit;
namespace RulesEngine.UnitTest
{
[ExcludeFromCodeCoverage]
public class MyObject
{
public string Name { get; set; }
public int Count { get; set; }
}
[ExcludeFromCodeCoverage]
public class ScopedParamsTest
{
@ -142,6 +151,34 @@ namespace RulesEngine.UnitTest
}
[Theory]
[InlineData("LocalParam_CorrectAnswer")]
public async Task LocalParam_GivesCorrectAnswer(string workflowName)
{
var workflow = GetWorkflowList();
var reSettingsWithCustomTypes = new ReSettings { CustomTypes = new Type[] { } };
var bre = new RulesEngine(workflow, reSettingsWithCustomTypes);
var myObject = new MyObject() {
Name = "My Object",
Count = 2
};
var rp1 = new RuleParameter("myObj", myObject);
List<RuleResultTree> resultList = await bre.ExecuteAllRulesAsync(workflowName, rp1);
Assert.True(resultList[0].IsSuccess);
myObject.Count = 3;
resultList = await bre.ExecuteAllRulesAsync(workflowName, rp1);
Assert.False(resultList[0].IsSuccess);
}
private void CheckResultTreeContainsAllInputs(string workflowName, List<RuleResultTree> result)
{
var workflow = GetWorkflowList().Single(c => c.WorkflowName == workflowName);
@ -393,6 +430,32 @@ namespace RulesEngine.UnitTest
Expression = "globalParam1.ToUpper() == \"HELLO\""
}
}
},
new Workflow {
WorkflowName = "LocalParam_CorrectAnswer",
Rules = new List<Rule> {
new Rule
{
RuleName = "Test Rule",
LocalParams = new List<LocalParam>
{
new LocalParam
{
Name = "threshold",
Expression = "3"
},
new LocalParam
{
Name = "myList",
Expression = "new int[]{ 1, 2, 3, 4, 5 }"
}
},
SuccessEvent = "Count is within tolerance.",
ErrorMessage = "Not as expected.",
Expression = "myList.Where(x => x < threshold).Contains(myObj.Count)",
RuleExpressionType = RuleExpressionType.LambdaExpression
}
}
}
};
}

View File

@ -0,0 +1,51 @@
{
"WorkflowName": "MyWorkflow",
"WorkflowsToInject": null,
"RuleExpressionType": 0,
"GlobalParams": [
{
"Name": "threshold",
"Expression": "double.Parse(\u00220.25\u0022)"
}
],
"Rules": [
{
"RuleName": "Activation",
"Properties": null,
"Operator": null,
"ErrorMessage": null,
"Enabled": true,
"RuleExpressionType": 0,
"WorkflowsToInject": null,
"Rules": null,
"LocalParams": [
{
"Name": "ruleCount",
"Expression": "int.Parse(\u002215\u0022)"
}
],
"Expression": "input1.Count \u003E= ruleCount \u0026\u0026 input1.Where(x =\u003E x.Value \u003E= threshold).Count() \u003E= ruleCount",
"Actions": null,
"SuccessEvent": null
},
{
"RuleName": "Deactivation",
"Properties": null,
"Operator": null,
"ErrorMessage": null,
"Enabled": true,
"RuleExpressionType": 0,
"WorkflowsToInject": null,
"Rules": null,
"LocalParams": [
{
"Name": "ruleCount",
"Expression": "int.Parse(\u002230\u0022)"
}
],
"Expression": "input1.Count \u003E= ruleCount \u0026\u0026 input1.OrderByDescending(o =\u003E o.ChangeDateTime).Take(ruleCount).All(a =\u003E a.Value \u003C threshold)",
"Actions": null,
"SuccessEvent": null
}
]
}