Skip to content

Commit

Permalink
Merge pull request #3 from runxc1/master
Browse files Browse the repository at this point in the history
Sync with runxc1/MicroRuleEngine
  • Loading branch information
jamescurran committed Oct 14, 2019
2 parents 76ac6c2 + 7523630 commit 3f96470
Show file tree
Hide file tree
Showing 14 changed files with 1,436 additions and 685 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -23,3 +23,4 @@ content
/ConsoleApp1-2.psess
/ConsoleApp1-1.psess
/MicroRuleEngine/MRE1.cs
privateKey.key
282 changes: 282 additions & 0 deletions MicroRuleEngine.Core.Tests/ExampleUsage.cs
@@ -0,0 +1,282 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MicroRuleEngine.Core.Tests.Models;

namespace MicroRuleEngine.Tests
{
/// <summary>
/// Summary description for UnitTest1
/// </summary>
[TestClass]
public class ExampleUsage
{
[TestMethod]
public void ChildPropertiesOfNull()
{
Order order = GetOrder();
order.Customer = null;
Rule rule = new Rule
{
MemberName = "Customer.Country.CountryCode",
Operator = ExpressionType.Equal.ToString("g"),
TargetValue = "AUS"
};
MRE engine = new MRE();
var compiledRule = engine.CompileRule<Order>(rule);
bool passes = compiledRule(order);
Assert.IsFalse(passes);
}

[TestMethod]
public void GetAllField()
{
Order order = GetOrder();

var type = order.GetType();
var members = MRE.Member.GetFields(type);
Assert.IsTrue(
members.Where(x=> x.Name == "Customer.Country.CountryCode" && x.PossibleOperators.Any(y=> y.Name == "StartsWith")).Any()
);
}

[TestMethod]
public void CoerceMethod()
{
Order order = GetOrder();
Rule rule = new Rule
{
MemberName = "Codes",
Operator = "Contains",
TargetValue = "243",
Inputs = new List<object>() { "243" }
};
MRE engine = new MRE();
var compiledRule = engine.CompileRule<Order>(rule);
bool passes = compiledRule(order);
Assert.IsTrue(passes);

order.Codes.Clear();
passes = compiledRule(order);
Assert.IsFalse(passes);
}

[TestMethod]
public void ChildProperties()
{
Order order = GetOrder();
Rule rule = new Rule
{
MemberName = "Customer.Country.CountryCode",
Operator = ExpressionType.Equal.ToString("g"),
TargetValue = "AUS"
};
MRE engine = new MRE();
var compiledRule = engine.CompileRule<Order>(rule);
bool passes = compiledRule(order);
Assert.IsTrue(passes);

order.Customer.Country.CountryCode = "USA";
passes = compiledRule(order);
Assert.IsFalse(passes);
}

[TestMethod]

public void ConditionalLogic()
{
Order order = GetOrder();
Rule rule = new Rule
{
Operator = ExpressionType.AndAlso.ToString("g"),
Rules = new List<Rule>
{
new Rule { MemberName = "Customer.LastName", TargetValue = "Doe", Operator = "Equal"},
new Rule
{
Operator = "Or",
Rules = new List<Rule>
{
new Rule { MemberName = "Customer.FirstName", TargetValue = "John", Operator = "Equal"},
new Rule { MemberName = "Customer.FirstName", TargetValue = "Jane", Operator = "Equal"}
}
}
}
};
MRE engine = new MRE();
var fakeName = engine.CompileRule<Order>(rule);
bool passes = fakeName(order);
Assert.IsTrue(passes);

order.Customer.FirstName = "Philip";
passes = fakeName(order);
Assert.IsFalse(passes);
}

[TestMethod]
public void BooleanMethods()
{
Order order = GetOrder();
Rule rule = new Rule
{
Operator = "HasItem",//The Order Object Contains a method named 'HasItem' that returns true/false
Inputs = new List<object> { "Test" }
};
MRE engine = new MRE();

var boolMethod = engine.CompileRule<Order>(rule);
bool passes = boolMethod(order);
Assert.IsTrue(passes);

var item = order.Items.First(x => x.ItemCode == "Test");
item.ItemCode = "Changed";
passes = boolMethod(order);
Assert.IsFalse(passes);
}

[TestMethod]
public void BooleanMethods_ByType()
{
Order order = GetOrder();
Rule rule = new Rule
{
Operator = "HasItem",//The Order Object Contains a method named 'HasItem' that returns true/false
Inputs = new List<object> { "Test" }
};
MRE engine = new MRE();

var boolMethod = engine.CompileRule(typeof(Order), rule);
bool passes =(bool) boolMethod.DynamicInvoke(order);
Assert.IsTrue(passes);

var item = order.Items.First(x => x.ItemCode == "Test");
item.ItemCode = "Changed";
passes = (bool)boolMethod.DynamicInvoke(order);
Assert.IsFalse(passes);
}

[TestMethod]
public void AnyOperator()
{
Order order = GetOrder();
//order.Items.Any(a => a.ItemCode == "test")
Rule rule = new Rule
{
MemberName = "Items",// The array property
Operator = "Any",
Rules = new[]
{
new Rule
{
MemberName = "ItemCode", // the property in the above array item
Operator = "Equal",
TargetValue = "Test",
}
}
};
MRE engine = new MRE();
var boolMethod = engine.CompileRule<Order>(rule);
bool passes = boolMethod(order);
Assert.IsTrue(passes);

var item = order.Items.First(x => x.ItemCode == "Test");
item.ItemCode = "Changed";
passes = boolMethod(order);
Assert.IsFalse(passes);
}



[TestMethod]
public void ChildPropertyBooleanMethods()
{
Order order = GetOrder();
Rule rule = new Rule
{
MemberName = "Customer.FirstName",
Operator = "EndsWith",//Regular method that exists on string.. As a note expression methods are not available
Inputs = new List<object> { "ohn" }
};
MRE engine = new MRE();
var childPropCheck = engine.CompileRule<Order>(rule);
bool passes = childPropCheck(order);
Assert.IsTrue(passes);

order.Customer.FirstName = "jane";
passes = childPropCheck(order);
Assert.IsFalse(passes);
}

[TestMethod]
public void ChildPropertyOfNullBooleanMethods()
{
Order order = GetOrder();
order.Customer = null;
Rule rule = new Rule
{
MemberName = "Customer.FirstName",
Operator = "EndsWith", //Regular method that exists on string.. As a note expression methods are not available
Inputs = new List<object> { "ohn" }
};
MRE engine = new MRE();
var childPropCheck = engine.CompileRule<Order>(rule);
bool passes = childPropCheck(order);
Assert.IsFalse(passes);
}
[TestMethod]
public void RegexIsMatch()//Had to add a Regex evaluator to make it feel 'Complete'
{
Order order = GetOrder();
Rule rule = new Rule
{
MemberName = "Customer.FirstName",
Operator = "IsMatch",
TargetValue = @"^[a-zA-Z0-9]*$"
};
MRE engine = new MRE();
var regexCheck = engine.CompileRule<Order>(rule);
bool passes = regexCheck(order);
Assert.IsTrue(passes);

order.Customer.FirstName = "--NoName";
passes = regexCheck(order);
Assert.IsFalse(passes);
}

public static Order GetOrder()
{
Order order = new Order()
{
OrderId = 1,
Customer = new Customer()
{
FirstName = "John",
LastName = "Doe",
Country = new Country()
{
CountryCode = "AUS"
}
},
Items = new List<Item>()
{
new Item { ItemCode = "MM23", Cost=5.25M},
new Item { ItemCode = "LD45", Cost=5.25M},
new Item { ItemCode = "Test", Cost=3.33M},
},
Codes = new List<int>()
{
555,
321,
243
},
Total = 13.83m,
OrderDate = new DateTime(1776, 7, 4),
Status = Status.Open

};
return order;
}
}
}
57 changes: 57 additions & 0 deletions MicroRuleEngine.Core.Tests/ExpressionToSQLQueryTest.cs
@@ -0,0 +1,57 @@
using EFModeling.Samples.DataSeeding;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MicroRuleEngine.Core.Tests
{
[TestClass]
public class ExpressionToSQLQueryTest
{
internal DbContextOptions<BloggingContext> GetDBOptions()
{
var connection = new SqliteConnection("DataSource=:memory:");
connection.Open();
var options = new DbContextOptionsBuilder<BloggingContext>()
.UseSqlite(connection)
.Options;

// Create the schema in the database
using (var context = new BloggingContext(options))
{
context.Database.EnsureCreated();
}
return options;
}
[TestMethod]
public void BasicEqualityExpression()
{

using (var context = new BloggingContext(GetDBOptions()))
{
context.Blogs.Add(new Blog { Url = "http://test.com" });
context.SaveChanges();

var testBlog = context.Blogs.FirstOrDefault(b => b.Url == "http://test.com");

var fields = MRE.Member.GetFields(typeof(Blog));
Rule rule = new Rule
{
MemberName = "Url",
Operator = mreOperator.Equal.ToString("g"),
TargetValue = "http://test.com"
};

var blog2 = context.Blogs.Where(MRE.ToExpression<Blog>(rule, false)).FirstOrDefault();

Assert.IsTrue(testBlog.BlogId == blog2.BlogId);

}
}
}
}
20 changes: 20 additions & 0 deletions MicroRuleEngine.Core.Tests/MicroRuleEngine.Core.Tests.csproj
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\MicroRuleEngine\MicroRuleEngine.csproj" />
</ItemGroup>

</Project>

0 comments on commit 3f96470

Please sign in to comment.