public void PerformanceTest()
        {
            const int MAXLOOPS = 4000;

            TestInput[] ti =
            {
                new TestInput(status.istrue,  "1 && (0 || 1) && 5 > 2"),
                new TestInput(status.isfalse, "1 && (!0 || 1) && 2 > 2")
            };

            LogicExpressionEvaluator_Accessor target = new LogicExpressionEvaluator_Accessor();
            int startms = System.Environment.TickCount;

            for (int i = 0; i < ti.Length; i++)
            {
                status retStatus = status.incomplete;
                for (int loop = 0; loop < MAXLOOPS; loop++)
                {
                    retStatus = LogicExpressionEvaluator_Accessor.Evaluate(ti[i].e);
                }

                Assert.AreEqual(ti[i].expected, retStatus, ti[i].e);
            }
            int endms = System.Environment.TickCount;
            int elapsedms_evaluate = endms - startms;

            startms = System.Environment.TickCount;
            for (int i = 0; i < ti.Length; i++)
            {
                for (int loop = 0; loop < MAXLOOPS; loop++)
                {
                    LogicExpressionEvaluator_Accessor.ValidateExpression(ti[i].e);
                }
            }
            endms = System.Environment.TickCount;
            int elapsedms_validate        = endms - startms;
            int evaluations               = MAXLOOPS * ti.Length;
            int elapsedmicroseconds       = elapsedms_evaluate * 1000;
            int microsecondsperevaluation = elapsedmicroseconds / evaluations;

            // How fast is the regular expression in .NET ?
            int    js_startms = System.Environment.TickCount;
            object response   = new object();

            for (int i = 0; i < ti.Length; i++)
            {
                for (int loop = 0; loop < MAXLOOPS; loop++)
                {
                    response = LogicExpressionEvaluatorTest.EvalJScript(ti[i].e);
                }
            }
            int js_endms = System.Environment.TickCount;
            int js_elapsedms_evaluate        = js_endms - js_startms;
            int js_elapsedmicroseconds       = js_elapsedms_evaluate * 1000;
            int js_microsecondsperevaluation = js_elapsedmicroseconds / evaluations;

            string msg = string.Format("{0} ms elapsed, {1} ms for validate ({2} expressions evaluated) {3} microseconds/eval [JS {4} microseconds/eval]", elapsedms_evaluate, elapsedms_validate, evaluations, microsecondsperevaluation, js_microsecondsperevaluation);

            // we want to be at least 50% faster than the JavaScript engine (with evaluation no less!)
            int targetmicrosecondsperevaluation = microsecondsperevaluation / 2 + microsecondsperevaluation;

            Assert.IsTrue((js_microsecondsperevaluation > targetmicrosecondsperevaluation), msg);
        }
        public void EvaluateTest()
        {
            TestInput[] ti =
            {
                new TestInput(status.istrue,            "1 && !0"),
                new TestInput(status.istrue,            "!0"),
                new TestInput(status.istrue,            "!0.0"),
                new TestInput(status.isfalse,           "!1"),
                new TestInput(status.isfalse,           "!37.42385"),
                new TestInput(status.isfalse,           "!(1)"),
                new TestInput(status.istrue,            "!(0)"),
                new TestInput(status.istrue,            "57 > !63"),
                new TestInput(status.istrue,            "!(0) || !(1) && (57 > 42.3) || !47"),
                new TestInput(status.isfalse,           "[!(0) || !(1) && (57 > 42.3) || !47] && 0"),
                new TestInput(status.isfalse,           "!(!(0) || !(1) && (57 > 42.3) || !47)"),

                new TestInput(status.istrue,            "1 != 0"),
                new TestInput(status.isfalse,           "25.3 != 25.3"),

                new TestInput(status.istrue,            "121.347"),
                new TestInput(status.isfalse,           "0.0"),
                new TestInput(status.istrue,            "58"),
                new TestInput(status.isfalse,           "0"),
                new TestInput(status.istrue,            "321.2 = 321.2"),
                new TestInput(status.istrue,            "(121.347)"),
                new TestInput(status.isfalse,           "(0.0)"),
                new TestInput(status.istrue,            "(58)"),
                new TestInput(status.isfalse,           "(0)"),
                new TestInput(status.istrue,            "(321.2 = 321.2)"),

                new TestInput(status.istrue,            "123.2 > 123.1"),
                new TestInput(status.istrue,            "537.89 < 788.47"),
                new TestInput(status.istrue,            "321.2 = 321.2"),
                new TestInput(status.isfalse,           "321.2 = 321.1"),
                new TestInput(status.istrue,            "57 = 57"),
                new TestInput(status.isfalse,           "57 = -57"),
                new TestInput(status.isundefined,       "57 = x"),
                new TestInput(status.isfalse,           "6380.5672 < 1043.61"),
                new TestInput(status.isfalse,           "57.8973 > 100.42"),

                new TestInput(status.istrue,            "-5 < 2"),
                new TestInput(status.istrue,            "5 > 2"),
                new TestInput(status.istrue,            "50 < 10043"),

                new TestInput(status.isfalse,           "12 < 4"),
                new TestInput(status.isfalse,           "47 > 89"),

                new TestInput(status.istrue,            "(1 && 0) || (1 && 1)"),
                new TestInput(status.isfalse,           "((1 && 0) || (1 && 1)) && 0"),
                new TestInput(status.isundefined,       "((1 && 0) || (1 && 1)) && x"),
                new TestInput(status.isfalse,           "(1 && 0) || (1 && 0)"),
                new TestInput(status.istrue,            "1 || 0 && 0"),
                new TestInput(status.isfalse,           "(1 || 0) && 0"),

                new TestInput(status.istrue,            "1 && 1"),
                new TestInput(status.isfalse,           "1 && 0"),
                new TestInput(status.istrue,            "1 || 0 && 1"),
                new TestInput(status.istrue,            "1 && 1 || 1 && 0"),
                new TestInput(status.istrue,            "1 || 0 && 1 && 1"),
                new TestInput(status.isfalse,           "1 && 1 && 0 && 1"),

                new TestInput(status.isundefined,       "1 && x"),
                new TestInput(status.isfalse,           "0 && x && 0 && 1"),
                new TestInput(status.isundefined,       "0 || x"),
                new TestInput(status.istrue,            "1 || x"),

                new TestInput(status.istrue,            "1 || true"),
                new TestInput(status.isfalse,           "1 && false"),
                new TestInput(status.istrue,            "1 && true"),
                new TestInput(status.isundefined,       "1 && true && x"),
                new TestInput(status.isfalse,           "1 && false && x"),

                new TestInput(status.incomplete,        "1 & false & x"),
                new TestInput(status.incomplete,        "1 | false | x"),

                new TestInput(status.isundefined,       "57 > x"),
                new TestInput(status.isundefined,       "x > x"),
                new TestInput(status.isundefined,       "x > 57"),

                new TestInput(status.isundefined,       "57 < x"),
                new TestInput(status.isundefined,       "x < x"),
                new TestInput(status.isundefined,       "x < 57"),

                new TestInput(status.isundefined,       "57 = x"),
                new TestInput(status.isundefined,       "x = x"),
                new TestInput(status.isundefined,       "x = 57"),

                new TestInput(status.isundefined,       "57 != x"),
                new TestInput(status.isundefined,       "x != x"),
                new TestInput(status.isundefined,       "x != 57"),

                new TestInput(status.isundefined,       "!x"),

                new TestInput(status.isfalse,           "0 && 1"),

                new TestInput(status.invalidexpression, "ABCD***"),
                new TestInput(status.noexpression,      "")
            };

            LogicExpressionEvaluator_Accessor target = new LogicExpressionEvaluator_Accessor();

            for (int i = 0; i < ti.Length; i++)
            {
                try
                {
                    status retStatus = LogicExpressionEvaluator_Accessor.Evaluate(ti[i].e);
                    Assert.AreEqual(ti[i].expected, retStatus, ti[i].e);

                    if (!ti[i].e.Contains("x") && (ti[i].expected == status.istrue || ti[i].expected == status.isfalse))
                    {
                        string response       = (LogicExpressionEvaluatorTest.EvalJScript(ti[i].e)).ToString();
                        status jscript_status = status.isfalse;
                        if (response.ToLower() == "true")
                        {
                            jscript_status = status.istrue;
                        }

                        // Since the JavaScript engine can return things other than true/false, we'll only verify true/false responses
                        if ((response.ToLower() == "true") || (response.ToLower() == "false"))
                        {
                            Assert.AreEqual(ti[i].expected, jscript_status, "JScript evaluation was \"" + response + "\" for expression \"" + ti[i].e + "\"");
                        }
                    }
                }
                catch (Exception ex)
                {
                    string msg = ex.Message;
                    throw;
                }
            }
        }