using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using NUnit.Framework; namespace DynamicExpresso.UnitTest { [TestFixture] public class OtherTests { [Test] public void Space_Characters_Are_Ignored() { var target = new Interpreter(); Assert.That(target.Eval(" 45\t\t + 1 \r \n"), Is.EqualTo(46)); } [Test] public void Empty_Null_Withespace_Expression() { var target = new Interpreter(); Assert.That(target.Eval(""), Is.Null); Assert.That(target.Parse("").ReturnType, Is.EqualTo(typeof(void))); Assert.That(target.Eval(null), Is.Null); Assert.That(target.Parse(null).ReturnType, Is.EqualTo(typeof(void))); Assert.That(target.Eval(" \t\t\r\n \t "), Is.Null); Assert.That(target.Parse(" \t\t\r\n \t ").ReturnType, Is.EqualTo(typeof(void))); } [Test] public void Complex_expression() { var target = new Interpreter(); var x = new MyTestService(); var y = 5; var parameters = new[] { new Parameter("x", x.GetType(), x), new Parameter("y", y.GetType(), y), }; Assert.That(target.Eval("x.AProperty >\t y && \r\n x.HelloWorld().Length == 10", parameters), Is.EqualTo(x.AProperty > y && x.HelloWorld().Length == 10)); Assert.That(target.Eval("x.AProperty * (4 + 65) / x.AProperty", parameters), Is.EqualTo(x.AProperty * (4 + 65) / x.AProperty)); Assert.That(target.Eval("Convert.ToString(x.AProperty * (4 + 65) / x.AProperty)", parameters), Is.EqualTo(Convert.ToString(x.AProperty * (4 + 65) / x.AProperty))); } [Test] public void Parse_An_Expression_And_Invoke_It_With_Different_Parameters() { var service = new MyTestService(); var target = new Interpreter() .SetVariable("service", service); var func = target.Parse("x > 4 ? service.VoidMethod() : service.VoidMethod2()", new Parameter("x", typeof(int))); Assert.That(func.ReturnType, Is.EqualTo(typeof(void))); Assert.That(service.VoidMethodCalled, Is.EqualTo(0)); Assert.That(service.VoidMethod2Called, Is.EqualTo(0)); func.Invoke(new Parameter("x", 5)); Assert.That(service.VoidMethodCalled, Is.EqualTo(1)); Assert.That(service.VoidMethod2Called, Is.EqualTo(0)); func.Invoke(new Parameter("x", 2)); Assert.That(service.VoidMethodCalled, Is.EqualTo(1)); Assert.That(service.VoidMethod2Called, Is.EqualTo(1)); } [Test] public void Should_Understand_ReturnType_Of_expressions() { var target = new Interpreter(); var x = new MyTestService(); var y = 5; var parameters = new[] { new Parameter("x", x.GetType(), x), new Parameter("y", y.GetType(), y), }; Assert.That(target.Parse("x.AProperty > y && x.HelloWorld().Length == 10", parameters).ReturnType, Is.EqualTo(typeof(bool))); Assert.That(target.Parse("x.AProperty * (4 + 65) / x.AProperty", parameters).ReturnType, Is.EqualTo(typeof(int))); } [Test] public void Execute_the_same_function_multiple_times() { var target = new Interpreter(); var functionX = target.Parse("Math.Pow(x, y) + 5", new Parameter("x", typeof(double)), new Parameter("y", typeof(double))); Assert.That(functionX.Invoke(15, 12), Is.EqualTo(Math.Pow(15, 12) + 5)); Assert.That(functionX.Invoke(5, 1), Is.EqualTo(Math.Pow(5, 1) + 5)); Assert.That(functionX.Invoke(11, 8), Is.EqualTo(Math.Pow(11, 8) + 5)); Assert.That(functionX.Invoke(new Parameter("x", 3.0), new Parameter("y", 4.0)), Is.EqualTo(Math.Pow(3, 4) + 5)); Assert.That(functionX.Invoke(new Parameter("x", 9.0), new Parameter("y", 2.0)), Is.EqualTo(Math.Pow(9, 2) + 5)); Assert.That(functionX.Invoke(new Parameter("x", 1.0), new Parameter("y", 3.0)), Is.EqualTo(Math.Pow(1, 3) + 5)); } [Test] public void Linq_Where() { var customers = new List { new Customer() { Name = "David", Age = 31, Gender = 'M' }, new Customer() { Name = "Mary", Age = 29, Gender = 'F' }, new Customer() { Name = "Jack", Age = 2, Gender = 'M' }, new Customer() { Name = "Marta", Age = 1, Gender = 'F' }, new Customer() { Name = "Moses", Age = 120, Gender = 'M' }, }; string whereExpression = "customer.Age > 18 && customer.Gender == 'F'"; var interpreter = new Interpreter(); Func dynamicWhere = interpreter.ParseAsDelegate>(whereExpression, "customer"); Assert.That(customers.Where(dynamicWhere).Count(), Is.EqualTo(1)); } [Test] public void Linq_Where2() { var prices = new[] { 5, 8, 6, 2 }; var whereFunction = new Interpreter() .ParseAsDelegate>("arg > 5"); Assert.That(prices.Where(whereFunction).Count(), Is.EqualTo(2)); } [Test] public void Linq_Queryable_Expression_Where() { IQueryable customers = (new List { new Customer() { Name = "David", Age = 31, Gender = 'M' }, new Customer() { Name = "Mary", Age = 29, Gender = 'F' }, new Customer() { Name = "Jack", Age = 2, Gender = 'M' }, new Customer() { Name = "Marta", Age = 1, Gender = 'F' }, new Customer() { Name = "Moses", Age = 120, Gender = 'M' }, }).AsQueryable(); string whereExpression = "customer.Age > 18 && customer.Gender == 'F'"; var interpreter = new Interpreter(); Expression> expression = interpreter.ParseAsExpression>(whereExpression, "customer"); Assert.That(customers.Where(expression).Count(), Is.EqualTo(1)); } [Test] public void Multiple_Parentheses_Math_Expression() { var interpreter = new Interpreter(); Assert.That(interpreter.Eval("2 + ((1 + 5) * (2 - 1))"), Is.EqualTo(2 + ((1 + 5) * (2 - 1)))); Assert.That(interpreter.Eval("2 + ((((1 + 5))) * (((2 - 1))+5.5))"), Is.EqualTo(2 + ((((1 + 5))) * (((2 - 1)) + 5.5)))); } [Test] public void Multiple_Parentheses_Cast_Expression() { var interpreter = new Interpreter(); Assert.That(interpreter.Eval("((double)5).GetType().Name"), Is.EqualTo(((double)5).GetType().Name)); } private class MyTestService { public DateTime AField = DateTime.Now; public DateTime AFIELD = DateTime.UtcNow; public int AProperty { get { return 769; } } public int APROPERTY { get { return 887; } } public string HelloWorld() { return "Ciao mondo"; } public string HELLOWORLD() { return "HELLO"; } public int VoidMethodCalled { get; set; } public void VoidMethod() { System.Diagnostics.Debug.WriteLine("VoidMethod called"); VoidMethodCalled++; } public int VoidMethod2Called { get; set; } public void VoidMethod2() { System.Diagnostics.Debug.WriteLine("VoidMethod2 called"); VoidMethod2Called++; } } private class Customer { public string Name { get; set; } public int Age { get; set; } public char Gender { get; set; } } } }