public async Task ExecuteRule_SpecialCharInWorkflowName_RunsSuccessfully() { var workflow = new WorkflowRules { WorkflowName = "Exámple", Rules = new Rule[] { new Rule { RuleName = "RuleWithLocalParam", RuleExpressionType = RuleExpressionType.LambdaExpression, Expression = "input1 == null || input1.hello.world = \"wow\"" } } }; var workflowStr = "{\"WorkflowName\":\"Exámple\",\"WorkflowRulesToInject\":null,\"GlobalParams\":null,\"Rules\":[{\"RuleName\":\"RuleWithLocalParam\",\"Properties\":null,\"Operator\":null,\"ErrorMessage\":null,\"Enabled\":true,\"ErrorType\":\"Warning\",\"RuleExpressionType\":\"LambdaExpression\",\"WorkflowRulesToInject\":null,\"Rules\":null,\"LocalParams\":null,\"Expression\":\"input1 == null || input1.hello.world = \\\"wow\\\"\",\"Actions\":null,\"SuccessEvent\":null}]}"; var re = new RulesEngine(new string[] { workflowStr }, null, null); // re.AddWorkflow(workflowStr); dynamic input1 = new ExpandoObject(); input1.hello = new ExpandoObject(); input1.hello.world = "wow"; List <RuleResultTree> result3 = await re.ExecuteAllRulesAsync("Exámple", input1); Assert.True(result3.All(c => c.IsSuccess)); }
public async Task ExecuteRule_RuntimeError_IgnoreException_DoesNotReturnException() { var workflow = new WorkflowRules { WorkflowName = "TestWorkflow", Rules = new[] { new Rule { RuleName = "ruleWithRuntimeError", Expression = "input1.Country.ToLower() == \"india\"" } } }; var re = new RulesEngine(new[] { workflow }, null, new ReSettings { IgnoreException = true }); var input = new RuleTestClass { Country = null }; var result = await re.ExecuteAllRulesAsync("TestWorkflow", input); Assert.NotNull(result); Assert.All(result, rule => Assert.False(rule.IsSuccess)); Assert.All(result, rule => Assert.Empty(rule.ExceptionMessage)); }
public static RulesEngine.RulesEngine GetRulesEngine(List <ConfigRulesModel> list) { var data = new { WorkflowName = "inputWorkflow", Rules = list.Select((t, i) => new { RuleName = (t.RuleName + i.ToString()), Expression = t.ShallowExpression, SuccessEvent = (t.Node + $"_{t.RuleType}"), RuleExpressionType = t.RuleExpressionType, }) }.ToJson(); var injectWorkflow = new WorkflowRules { WorkflowName = "inputWorkflowReference", WorkflowRulesToInject = new List <string> { "inputWorkflow" } }; var injectWorkflowStr = JsonConvert.SerializeObject(injectWorkflow); var mockLogger = new Mock <ILogger>(); return(new RulesEngine.RulesEngine(new string[] { data, injectWorkflowStr }, mockLogger.Object)); }
public async Task ExecuteRule_AddOrUpdateWorkflow_ExecutesUpdatedRules(string previousWorkflowFile, string newWorkflowFile) { var re = GetRulesEngine(previousWorkflowFile); dynamic input1 = GetInput1(); dynamic input2 = GetInput2(); dynamic input3 = GetInput3(); // Run previous rules. List <RuleResultTree> result1 = await re.ExecuteAllRulesAsync("inputWorkflow", input1, input2, input3); Assert.NotNull(result1); Assert.IsType <List <RuleResultTree> >(result1); Assert.Contains(result1, c => c.IsSuccess); // Fetch and update new rules. WorkflowRules newWorkflowRules = ParseAsWorkflowRules(newWorkflowFile); re.AddOrUpdateWorkflow(newWorkflowRules); // Run new rules. List <RuleResultTree> result2 = await re.ExecuteAllRulesAsync("inputWorkflow", input1, input2, input3); Assert.NotNull(result2); Assert.IsType <List <RuleResultTree> >(result2); Assert.DoesNotContain(result2, c => c.IsSuccess); // New execution should have different result than previous execution. var previousResults = result1.Select(c => new { c.Rule.RuleName, c.IsSuccess }); var newResults = result2.Select(c => new { c.Rule.RuleName, c.IsSuccess }); Assert.NotEqual(previousResults, newResults); }
public async Task ClearWorkFlow_ShouldRemoveAllCompiledCache() { var workflow = new WorkflowRules { WorkflowName = "Test", Rules = new Rule[] { new Rule { RuleName = "RuleWithLocalParam", LocalParams = new LocalParam[] { new LocalParam { Name = "lp1", Expression = "true" } }, RuleExpressionType = RuleExpressionType.LambdaExpression, Expression = "lp1 == true" } } }; var re = new RulesEngine(); re.AddWorkflow(workflow); var result1 = await re.ExecuteAllRulesAsync("Test", "hello"); Assert.True(result1.All(c => c.IsSuccess)); re.ClearWorkflows(); workflow.Rules.First().LocalParams.First().Expression = "false"; re.AddWorkflow(workflow); var result2 = await re.ExecuteAllRulesAsync("Test", "hello"); Assert.True(result2.All(c => c.IsSuccess == false)); }
public void RulesEngine_New_IncorrectJSON_ThrowsException() { Assert.Throws<RuleValidationException>(() => { var workflow = new WorkflowRules(); var re = CreateRulesEngine(workflow); }); Assert.Throws<RuleValidationException>(() => { var workflow = new WorkflowRules() { WorkflowName = "test" }; var re = CreateRulesEngine(workflow); }); }
private WorkflowRules[] GetWorkflowRulesWithoutActions() { var workflow1 = new WorkflowRules { WorkflowName = "NoActionWorkflow", Rules = new List <Rule> { new Rule { RuleName = "NoActionTest", RuleExpressionType = RuleExpressionType.LambdaExpression, Expression = "1 == 1", } } }; return(new [] { workflow1 }); }
private RulesEngine GetRulesEngine(string filename, ReSettings reSettings = null) { var filePath = Path.Combine(Directory.GetCurrentDirectory() as string, "TestData", filename); var data = File.ReadAllText(filePath); var injectWorkflow = new WorkflowRules { WorkflowName = "inputWorkflowReference", WorkflowRulesToInject = new List<string> { "inputWorkflow" } }; var injectWorkflowStr = JsonConvert.SerializeObject(injectWorkflow); var mockLogger = new Mock<ILogger>(); return new RulesEngine(new string[] { data, injectWorkflowStr }, mockLogger.Object, reSettings); }
private RulesEngine GetRulesEngine(string filename, ReSettings reSettings = null) { var data = GetFileContent(filename); var injectWorkflow = new WorkflowRules { WorkflowName = "inputWorkflowReference", WorkflowRulesToInject = new List <string> { "inputWorkflow" } }; var injectWorkflowStr = JsonConvert.SerializeObject(injectWorkflow); var mockLogger = new Mock <ILogger>(); return(new RulesEngine(new string[] { data, injectWorkflowStr }, mockLogger.Object, reSettings)); }
/// <summary> /// 批量执行工作集 /// </summary> /// <param name="workflowRules"></param> /// <returns></returns> public IList <RuleResult> Execute(WorkflowRules workflowRules) { if (workflowRules.Rules == null || workflowRules.RuleInputs == null) { throw new ArgumentNullException("规则集或数据集不能为 null"); } if (workflowRules.Rules.Count != workflowRules.RuleInputs.Count) { throw new ArgumentOutOfRangeException($"规则集与数据集数量不一致:{workflowRules.Rules.Count}!={workflowRules.RuleInputs.Count}"); } int length = workflowRules.Rules.Count; for (int i = 0; i < length; i++) { workflowRules.RuleResults.Add(Execute(workflowRules.Rules[i], workflowRules.RuleInputs[i])); } return(workflowRules.RuleResults); }
public async Task ExecuteRule_RuntimeError_ThrowsException() { var workflow = new WorkflowRules { WorkflowName = "TestWorkflow", Rules = new[] { new Rule { RuleName = "ruleWithRuntimeError", Expression = "input1.Country.ToLower() == \"india\"" } } }; var re = new RulesEngine(new[] { workflow }, null, new ReSettings { EnableExceptionAsErrorMessage = false }); var input = new RuleTestClass { Country = null }; _ = await Assert.ThrowsAsync <RuleException>(async() => await re.ExecuteAllRulesAsync("TestWorkflow", input)); }
public async Task ExecuteRule_RuntimeError_ShouldReturnAsErrorMessage() { var workflow = new WorkflowRules { WorkflowName = "TestWorkflow", Rules = new[] { new Rule { RuleName = "ruleWithRuntimeError", Expression = "input1.Country.ToLower() == \"india\"" } } }; var re = new RulesEngine(new[] { workflow }, null, null); var input = new RuleTestClass { Country = null }; var result = await re.ExecuteAllRulesAsync("TestWorkflow", input); Assert.NotNull(result); Assert.All(result, rule => Assert.False(rule.IsSuccess)); Assert.All(result, rule => Assert.StartsWith("Error while executing rule :", rule.ExceptionMessage)); }
private WorkflowRules[] GetWorkflowWithActions() { var workflow1 = new WorkflowRules { WorkflowName = "ActionWorkflow", Rules = new List <Rule> { new Rule { RuleName = "ExpressionOutputRuleTest", RuleExpressionType = RuleExpressionType.LambdaExpression, Expression = "1 == 1", Actions = new Dictionary <ActionTriggerType, ActionInfo> { { ActionTriggerType.onSuccess, new ActionInfo { Name = "OutputExpression", Context = new Dictionary <string, object> { { "expression", "2*2" } } } } } }, new Rule { RuleName = "EvaluateRuleTest", RuleExpressionType = RuleExpressionType.LambdaExpression, Expression = "1 == 1", Actions = new Dictionary <ActionTriggerType, ActionInfo> { { ActionTriggerType.onSuccess, new ActionInfo { Name = "EvaluateRule", Context = new Dictionary <string, object> { { "workflowName", "ActionWorkflow" }, { "ruleName", "ExpressionOutputRuleTest" } } } } } } } }; return(new [] { workflow1 }); }
/// <summary> /// Lamda 表达式工作流的股票购买 /// </summary> public static void LambdaStockWorkFlowTest() { var rand = new Random(); var workflow = new WorkflowRules() { RuleInputs = new List <IDictionary <string, object> >(defaultCount), Rules = new List <Rule>(defaultCount) }; for (int i = 0; i < defaultCount; i++) { var rule = new Rule() { RuleExpressionType = RuleExpressionType.Lambda, RuleExpression = $"price < expectPrice", FaildMessage = "股价报价为:#(price)#,预期价位为:#(expectPrice)#,股价不匹配,取消购买", SucessMessage = "股价报价为:#(price)#,预期价位为:#(expectPrice)#, 当前余额:#(totalMoney)#,可买入,购买系数:#rate#(余额的比例),买入数量:#(Math.round(totalMoney*rate/price))#,买入后余额:#(totalMoney-Math.round(totalMoney*rate/price)*price)#", RuleName = "判断股价,价格匹配就买入", }; var dct = new Dictionary <string, object>(); dct["price"] = rand.Next(1, 100); dct["rate"] = rand.NextDouble(); dct["expectPrice"] = rand.Next(1, 100); dct["totalMoney"] = rand.Next(1, 100) * rand.Next(2, 200); workflow.Rules.Add(rule); workflow.RuleInputs.Add(dct); } // 执行 var resultList = ruleEngine.Execute(workflow); if (saveTestData) { File.WriteAllText($"{resultDataDir}{MethodBase.GetCurrentMethod().Name}.txt", JsonConvert.SerializeObject(resultList)); } }
public async Task ExecuteRule_WithNullInput_ShouldNotThrowException() { var workflow = new WorkflowRules { WorkflowName = "Test", Rules = new Rule[] { new Rule { RuleName = "RuleWithLocalParam", RuleExpressionType = RuleExpressionType.LambdaExpression, Expression = "input1 == null || input1.hello.world = \"wow\"" } } }; var re = new RulesEngine(); re.AddWorkflow(workflow); var result1 = await re.ExecuteAllRulesAsync("Test", new RuleParameter("input1", value : null)); Assert.True(result1.All(c => c.IsSuccess)); var result2 = await re.ExecuteAllRulesAsync("Test", new object[] { null }); Assert.True(result2.All(c => c.IsSuccess)); dynamic input1 = new ExpandoObject(); input1.hello = new ExpandoObject(); input1.hello.world = "wow"; List <RuleResultTree> result3 = await re.ExecuteAllRulesAsync("Test", input1); Assert.True(result3.All(c => c.IsSuccess)); }
private RulesEngine CreateRulesEngine(WorkflowRules workflow) { var json = JsonConvert.SerializeObject(workflow); return(new RulesEngine(new string[] { json }, null)); }
public bool HasResolved() { return(Handled && WorkflowRules?.Any() == true); }
public void AddOrUpdateWorkflowRules(string workflowName, WorkflowRules rules) { _workflowRules.AddOrUpdate(workflowName, rules, (k, v) => rules); }
public Task <IEnumerable <WorkflowRules> > GetRulesAsync(Type inputType, CancellationToken cancellationToken = default) { IEnumerable <WorkflowRules> rules = new WorkflowRules[0]; return(Task.FromResult(rules)); }