public void BasicEval()
        {
            var engine = new RecalcEngine();

            engine.UpdateVariable("M", 10.0);
            engine.UpdateVariable("M2", -4);
            var result = engine.Eval("M + Abs(M2)");

            Assert.Equal(14.0, ((NumberValue)result).Value);
        }
        public void CantChangeType()
        {
            var engine = new RecalcEngine();

            engine.UpdateVariable("a", FormulaValue.New(12));

            // not supported: Can't change a variable's type.
            Assert.Throws <NotSupportedException>(() =>
                                                  engine.UpdateVariable("a", FormulaValue.New("str"))
                                                  );
        }
        public void BasicRecalc()
        {
            var engine = new RecalcEngine();

            engine.UpdateVariable("A", 15);
            engine.SetFormula("B", "A*2", OnUpdate);
            AssertUpdate("B-->30;");

            engine.UpdateVariable("A", 20);
            AssertUpdate("B-->40;");

            // Ensure we can update to null.
            engine.UpdateVariable("A", FormulaValue.NewBlank(FormulaType.Number));
            AssertUpdate("B-->0;");
        }
        public void ChangeRecord()
        {
            var engine = new RecalcEngine();

            engine.UpdateVariable("R", FormulaValue.RecordFromFields(
                                      new NamedValue("F1", FormulaValue.NewBlank(FormulaType.Number)),
                                      new NamedValue("F2", FormulaValue.New(6))));

            engine.SetFormula("A", "R.F2 + 3 + R.F1", OnUpdate);
            AssertUpdate("A-->9;");

            engine.UpdateVariable("R", FormulaValue.RecordFromFields(
                                      new NamedValue("F1", FormulaValue.New(2)),
                                      new NamedValue("F2", FormulaValue.New(7))));
            AssertUpdate("A-->12;");
        }
        public void RecalcNoExtraCallbacks()
        {
            var engine = new RecalcEngine();

            engine.UpdateVariable("A1", 1);
            engine.UpdateVariable("A2", 5);

            engine.SetFormula("B", "A1+A2", OnUpdate);
            AssertUpdate("B-->6;");

            engine.SetFormula("C", "A2*10", OnUpdate);
            AssertUpdate("C-->50;");

            engine.UpdateVariable("A1", 2);
            AssertUpdate("B-->7;"); // Don't fire C, not touched

            engine.UpdateVariable("A2", 7);
            AssertUpdate("B-->9;C-->70;");
        }
        public void Recalc2()
        {
            var engine = new RecalcEngine();

            engine.UpdateVariable("A", 1);
            engine.SetFormula("B", "A*10", OnUpdate);
            AssertUpdate("B-->10;");

            engine.SetFormula("C", "B+5", OnUpdate);
            AssertUpdate("C-->15;");

            // depend on grand child directly
            engine.SetFormula("D", "B+A", OnUpdate);
            AssertUpdate("D-->11;");

            // Updating A will recalc both D and B.
            // But D also depends on B, so verify D pulls new value of B.
            engine.UpdateVariable("A", 2);

            // Batched up (we don't double fire)
            AssertUpdate("B-->20;C-->25;D-->22;");
        }