Esempio n. 1
0
        public void FormulaErrorUndefined()
        {
            var engine = new RecalcEngine();

            // formula fails since 'B' is undefined.
            Assert.Throws <InvalidOperationException>(() =>
                                                      engine.SetFormula("A", "B*2", OnUpdate));
        }
Esempio n. 2
0
        public void CheckBindError()
        {
            var engine = new RecalcEngine();
            var result = engine.Check("3+foo+2"); // foo is undefined

            Assert.False(result.IsSuccess);
            Assert.Single(result.Errors);
            Assert.StartsWith("Error 2-5: Name isn't valid. This identifier isn't recognized", result.Errors[0].ToString());
        }
Esempio n. 3
0
        public void CheckParseError()
        {
            var engine = new RecalcEngine();
            var result = engine.Check("3*1+");

            Assert.False(result.IsSuccess);
            Assert.Single(result.Errors);
            Assert.StartsWith("Error 4-4: Expected an operand", result.Errors[0].ToString());
        }
Esempio n. 4
0
        public void FormulaCantRedefine()
        {
            var engine = new RecalcEngine();

            engine.SetFormula("A", "2", OnUpdate);

            // Can't redefine an existing formula.
            Assert.Throws <InvalidOperationException>(() =>
                                                      engine.SetFormula("A", "3", OnUpdate));
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        public void PropagateNull()
        {
            var engine = new RecalcEngine();

            engine.SetFormula("A", expr: "Blank()", OnUpdate);
            engine.SetFormula("B", "A", OnUpdate);

            var b = engine.GetValue("B");

            Assert.True(b is BlankValue);
        }
Esempio n. 7
0
        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"))
                                                  );
        }
Esempio n. 8
0
        public void EvalWithGlobals()
        {
            var engine = new RecalcEngine();

            var context = FormulaValue.NewRecord(new
            {
                x = 15
            });
            var result = engine.Eval("With({y:2}, x+y)", context);

            Assert.Equal(17.0, ((NumberValue)result).Value);
        }
Esempio n. 9
0
        public void CheckBindEnum()
        {
            var engine = new RecalcEngine();
            var result = engine.Check("TimeUnit.Hours");

            Assert.True(result.IsSuccess);

            // The resultant type will be the underlying type of the enum provided to
            // check.  In the case of TimeUnit, this is StringType
            Assert.True(result.ReturnType is StringType);
            Assert.Empty(result.TopLevelIdentifiers);
        }
Esempio n. 10
0
        public void CheckSuccess()
        {
            var engine = new RecalcEngine();
            var result = engine.Check("3*2+x",
                                      new RecordType().Add(
                                          new NamedFormulaType("x", FormulaType.Number)));

            Assert.True(result.IsSuccess);
            Assert.True(result.ReturnType is NumberType);
            Assert.Single(result.TopLevelIdentifiers);
            Assert.Equal("x", result.TopLevelIdentifiers.First());
        }
Esempio n. 11
0
        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;");
        }
Esempio n. 12
0
        public void CustomFunction()
        {
            var engine = new RecalcEngine();

            engine.AddFunction(new TestCustomFunction());

            // Shows up in enuemeration
            var func = engine.GetAllFunctionNames().First(name => name == "TestCustom");

            Assert.NotNull(func);

            // Can be invoked.
            var result = engine.Eval("TestCustom(2,3)");

            Assert.Equal(6.0, result.ToObject());
        }
Esempio n. 13
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;");
        }
Esempio n. 14
0
        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;");
        }
Esempio n. 15
0
        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;");
        }
Esempio n. 16
0
        [InlineData("With({B:15}, B> A)", "A")]                         // B is shadowed
        public void T1(string expr, string dependsOn)
        {
            // var expected = new HashSet<string>(dependsOn.Split(','));

            var engine = new RecalcEngine();

            var accountType = new TableType()
                              .Add(new NamedFormulaType("Age", FormulaType.Number));

            var type = new RecordType()
                       .Add(new NamedFormulaType("A", FormulaType.Number))
                       .Add(new NamedFormulaType("B", FormulaType.Number))
                       .Add(new NamedFormulaType("Accounts", accountType));
            var result = engine.Check(expr, type);

            Assert.True(result.IsSuccess);

            // sets should be equal
            var sorted    = result.TopLevelIdentifiers.OrderBy(x => x).ToArray();
            var actualStr = string.Join(',', sorted);

            Assert.Equal(dependsOn, actualStr);
        }