public void TestCtorResolutionResolvesToExactMatchOfArgumentTypes()
        {
            TypeRegistry.RegisterType(typeof(Foo));
            Dictionary<string, object> args = new Dictionary<string, object>();
            args["bars"] = new Bar[] { new Bar() };

            // ensure noone changed our test class
            Foo foo1 = new Foo(1, (Bar[])args["bars"]);
            try
            {
                Foo foo2 = new Foo(1, (ICollection)args["bars"]);
            }
            catch (InvalidOperationException) { }

            Assert.IsNotNull(ExpressionEvaluator.GetValue(null, "new Foo(1, #bars)", args));
        }
        public void TestEqualityOperator()
        {
            // Null
            Assert.IsTrue((bool)ExpressionEvaluator.GetValue(null, "null == null"));
            Assert.IsFalse((bool)ExpressionEvaluator.GetValue(null, "null == 'xyz'"));
            Assert.IsFalse((bool)ExpressionEvaluator.GetValue(null, "123 == null"));
            Assert.IsFalse((bool)ExpressionEvaluator.GetValue(null, "null == 123"));

            // Bool
            Assert.IsTrue((bool)ExpressionEvaluator.GetValue(null, "false == false"));
            Assert.IsTrue((bool)ExpressionEvaluator.GetValue(null, "true == true"));
            Assert.IsFalse((bool)ExpressionEvaluator.GetValue(null, "false == true"));
            Assert.IsFalse((bool)ExpressionEvaluator.GetValue(null, "true == false"));

            // Int
            Assert.IsTrue((bool)ExpressionEvaluator.GetValue(null, "2 == 2"));
            Assert.IsTrue((bool)ExpressionEvaluator.GetValue(null, "-5 == -5"));
            Assert.IsFalse((bool)ExpressionEvaluator.GetValue(null, "2 == -5"));
            Assert.IsFalse((bool)ExpressionEvaluator.GetValue(null, "-5 == 2"));

            // String
            Assert.IsTrue((bool)ExpressionEvaluator.GetValue(null, "'test' == 'test'"));
            Assert.IsFalse((bool)ExpressionEvaluator.GetValue(null, "'Test' == 'test'"));
            Assert.IsFalse((bool)ExpressionEvaluator.GetValue(null, "'test' == 'Test'"));

            // DateTime
            Assert.IsTrue((bool)ExpressionEvaluator.GetValue(null, "date('1974-08-24') == date('1974-08-24')"));
            Assert.IsTrue((bool)ExpressionEvaluator.GetValue(null, "DateTime.Today == DateTime.Today"));
            Assert.IsFalse((bool)ExpressionEvaluator.GetValue(null, "DateTime.Today == date('1974-08-24')"));
            Assert.IsFalse((bool)ExpressionEvaluator.GetValue(null, "date('1974-08-24') == DateTime.Today"));

            // Enums
            Foo foo = new Foo(FooType.One);
            TypeRegistry.RegisterType("FooType", typeof(FooType));
            Assert.IsTrue((bool)ExpressionEvaluator.GetValue(foo, "Type == FooType.One"));
            Assert.IsTrue((bool)ExpressionEvaluator.GetValue(foo, "Type == 'One'"));
            Assert.IsFalse((bool)ExpressionEvaluator.GetValue(foo, "Type == 'Two'"));
            Assert.IsTrue((bool)ExpressionEvaluator.GetValue(foo, "FooType.One == Type"));
            Assert.IsTrue((bool)ExpressionEvaluator.GetValue(foo, "'One' == Type"));
            Assert.IsFalse((bool)ExpressionEvaluator.GetValue(foo, "'Two' == Type"));
        }
        public void TestNullableTypes()
        {
            Foo foo = new Foo();
            Assert.IsNull(ExpressionEvaluator.GetValue(foo, "NullableDate"));
            Assert.IsNull(ExpressionEvaluator.GetValue(foo, "NullableInt"));

            ExpressionEvaluator.SetValue(foo, "NullableDate", DateTime.Today);
            ExpressionEvaluator.SetValue(foo, "NullableDate", null);
            ExpressionEvaluator.SetValue(foo, "NullableDate", "2004-08-14");
            ExpressionEvaluator.SetValue(foo, "NullableDate", DateTime.Today);
            ExpressionEvaluator.SetValue(foo, "NullableInt", 1);
            ExpressionEvaluator.SetValue(foo, "NullableInt", null);
            ExpressionEvaluator.SetValue(foo, "NullableInt", "5");
            ExpressionEvaluator.SetValue(foo, "NullableInt", 1);

            Assert.IsInstanceOf(typeof(DateTime?), ExpressionEvaluator.GetValue(foo, "NullableDate"));
            Assert.IsInstanceOf(typeof(Int32?), ExpressionEvaluator.GetValue(foo, "NullableInt"));

            Assert.AreEqual(DateTime.Today, ExpressionEvaluator.GetValue(foo, "NullableDate"));
            Assert.AreEqual(1, ExpressionEvaluator.GetValue(foo, "NullableInt"));

            int? test = 1;
            Assert.IsInstanceOf(typeof(Int32?), ExpressionEvaluator.GetValue(test, "#root"));
            Assert.IsTrue((bool)ExpressionEvaluator.GetValue(test, "#root != null"));
            Assert.AreEqual(1, ExpressionEvaluator.GetValue(test, "#root"));

            test = null;
            Assert.IsTrue((bool)ExpressionEvaluator.GetValue(test, "#root == null"));
            Assert.IsNull(ExpressionEvaluator.GetValue(test, "#root"));
        }
        public void TestMethodResolutionWithParamArray()
        {
            Foo foo = new Foo();
            Assert.AreEqual("a|b|c", foo.MethodWithArrayArgument(new string[] { "a", "b", "c" }));
            Assert.AreEqual("a||c", foo.MethodWithArrayArgument(new string[] { "a", null, "c" }));
            Assert.AreEqual("a|b|c", foo.MethodWithParamArray("a", "b", "c"));
            Assert.AreEqual("a||c", foo.MethodWithParamArray("a", null, "c"));

            Assert.AreEqual("a|b|c", ExpressionEvaluator.GetValue(foo, "MethodWithArrayArgument(new string[] { 'a', 'b', 'c' })"));
            Assert.AreEqual("a||c", ExpressionEvaluator.GetValue(foo, "MethodWithArrayArgument(new string[] { 'a', null, 'c' })"));
            Assert.AreEqual("a|b|c", ExpressionEvaluator.GetValue(foo, "MethodWithParamArray('a', 'b', 'c')"));
            Assert.AreEqual("a||c", ExpressionEvaluator.GetValue(foo, "MethodWithParamArray('a', null, 'c')"));

            Assert.AreEqual("a|b|c", ExpressionEvaluator.GetValue(foo, "MethodWithParamArray(false, 'a', 'b', 'c')"));
            Assert.AreEqual("a||c", ExpressionEvaluator.GetValue(foo, "MethodWithParamArray(false, 'a', null, 'c')"));
            Assert.AreEqual("A|B|C", ExpressionEvaluator.GetValue(foo, "MethodWithParamArray(true, 'a', 'b', 'c')"));
            Assert.AreEqual("A||C", ExpressionEvaluator.GetValue(foo, "MethodWithParamArray(true, 'a', null, 'c')"));
        }
        public void TestMethodResolutionResolvesToExactMatchOfArgumentTypes()
        {
            Dictionary<string, object> args = new Dictionary<string, object>();
            args["bars"] = new Bar[] { new Bar() };
            Foo foo = new Foo();

            // ensure noone changed our test class
            Assert.AreEqual("ExactMatch", foo.MethodWithSimilarArguments(1, (Bar[])args["bars"]));
            Assert.AreEqual("AssignableMatch", foo.MethodWithSimilarArguments(1, (ICollection)args["bars"]));

            Assert.AreEqual("ExactMatch", ExpressionEvaluator.GetValue(foo, "MethodWithSimilarArguments(1, #bars)", args));
        }
        public void TestIndexerResolutionResolvesToExactMatchOfArgumentTypes()
        {
            Dictionary<string, object> args = new Dictionary<string, object>();
            args["bars"] = new Bar[] { new Bar() };
            Foo foo = new Foo();

            // ensure noone changed our test class
            Assert.AreEqual("ExactMatch", foo[(Bar[])args["bars"]]);
            Assert.AreEqual("AssignableMatch", foo[(ICollection)args["bars"]]);

            Assert.AreEqual("ExactMatch", ExpressionEvaluator.GetValue(foo, "#root[#bars]", args));
        }
        public void TestIndexedPropertyAccess()
        {
            TypeRegistry.RegisterType("Society", typeof(Society));

            // arrays and lists
            Assert.AreEqual("Induction motor", ExpressionEvaluator.GetValue(tesla, "Inventions[3]"));
            Assert.AreEqual("Nikola Tesla", ExpressionEvaluator.GetValue(ieee, "Members[0].Name"));
            Assert.AreEqual("Wireless communication", ExpressionEvaluator.GetValue(ieee, "Members[0].Inventions[6]"));

            // maps
            Assert.AreEqual(pupin, ExpressionEvaluator.GetValue(ieee, "Officers['president']"));
            Assert.AreEqual("Idvor", ExpressionEvaluator.GetValue(ieee, "Officers['president'].PlaceOfBirth.City"));
            Assert.AreEqual(tesla, ExpressionEvaluator.GetValue(ieee, "Officers['advisors'][0]"));
            Assert.AreEqual("Polyphase alternating-current system",
                            ExpressionEvaluator.GetValue(ieee, "Officers['advisors'][0].Inventions[2]"));

            // maps with non-literal parameters
            Dictionary<string, object> vars = new Dictionary<string, object>();
            vars["prez"] = "president";
            Assert.AreEqual(pupin, ExpressionEvaluator.GetValue(ieee, "Officers[#prez]", vars));

            Assert.AreEqual(pupin, ExpressionEvaluator.GetValue(ieee, "Officers[Society.President]"));
            Assert.AreEqual("Idvor", ExpressionEvaluator.GetValue(ieee, "Officers[Society.President].PlaceOfBirth.City"));
            Assert.AreEqual(tesla, ExpressionEvaluator.GetValue(ieee, "Officers[Society.Advisors][0]"));
            Assert.AreEqual("Polyphase alternating-current system",
                            ExpressionEvaluator.GetValue(ieee, "Officers[Society.Advisors][0].Inventions[2]"));

            // try to set some values
            ExpressionEvaluator.SetValue(ieee, "Officers['advisors'][0].PlaceOfBirth.Country", "Croatia");
            Assert.AreEqual("Croatia", ExpressionEvaluator.GetValue(tesla, "PlaceOfBirth.Country"));
            ExpressionEvaluator.SetValue(ieee, "Officers['president'].Name", "Michael Pupin");
            Assert.AreEqual("Michael Pupin", ExpressionEvaluator.GetValue(pupin, "Name"));
            ExpressionEvaluator.SetValue(ieee, "Officers['advisors']", new Inventor[] { pupin, tesla });
            Assert.AreEqual(pupin, ExpressionEvaluator.GetValue(ieee, "Officers['advisors'][0]"));
            Assert.AreEqual(tesla, ExpressionEvaluator.GetValue(ieee, "Officers['advisors'][1]"));

            // generic indexer
            Bar bar = new Bar();
            Foo foo = new Foo();
            IExpression exp = Expression.Parse("[1]");
            Assert.AreEqual(2, exp.GetValue(bar));
            Assert.AreEqual(2, exp.GetValue(bar));
            Assert.AreEqual("test_1", ExpressionEvaluator.GetValue(foo, "[1, 'test']"));
        }