public void ExpressionWithChainedMethodCalls_ReturnValidToken()
        {
            string input = "'a'.ToUpper0().ToUpper1(1).ToUpper2(7, 9.12).ToUpper3('abc', true, false, false, 'A') == \"A\"";
            IReadOnlyList <FilterExpressionToken> tokens = FilterExpressionTokenizer.Tokenize(input);

            Assert.Equal(3, tokens.Count);
            Assert.IsType <MethodCallExpressionToken>(tokens.First());

            MethodCallExpressionToken toUpper3 = tokens.First() as MethodCallExpressionToken;
            MethodCallExpressionToken toUpper2 = toUpper3.CalledOnExpression as MethodCallExpressionToken;
            MethodCallExpressionToken toUpper1 = toUpper2.CalledOnExpression as MethodCallExpressionToken;
            MethodCallExpressionToken toUpper0 = toUpper1.CalledOnExpression as MethodCallExpressionToken;

            Assert.Equal("ToUpper0", toUpper0.MethodName);
            Assert.Equal("ToUpper1", toUpper1.MethodName);
            Assert.Equal("ToUpper2", toUpper2.MethodName);
            Assert.Equal("ToUpper3", toUpper3.MethodName);

            Assert.Empty(toUpper0.Arguments);

            Assert.Single(toUpper1.Arguments);
            Assert.Equal(1.0, (toUpper1.Arguments[0] as ConstantNumberExpressionToken).Token.NumberValue, 6);

            Assert.Equal(2, toUpper2.Arguments.Length);
            Assert.Equal(7.0, (toUpper2.Arguments[0] as ConstantNumberExpressionToken).Token.NumberValue, 6);
            Assert.Equal(9.12, (toUpper2.Arguments[1] as ConstantNumberExpressionToken).Token.NumberValue, 6);

            Assert.Equal(5, toUpper3.Arguments.Length);
            Assert.Equal("abc", (toUpper3.Arguments[0] as ConstantStringExpressionToken).Token.StringValue);
            Assert.True((toUpper3.Arguments[1] as ConstantBoolExpressionToken).Token.BoolValue);
            Assert.False((toUpper3.Arguments[2] as ConstantBoolExpressionToken).Token.BoolValue);
            Assert.False((toUpper3.Arguments[3] as ConstantBoolExpressionToken).Token.BoolValue);
            Assert.Equal("A", (toUpper3.Arguments[4] as ConstantStringExpressionToken).Token.StringValue);
        }
        public void PropertyFilterSubExpression_DeeplyNestedProperty_ReturnsCorrectValue()
        {
            string json = @"
                {
                    `a`: {
                        `b`: {
                            `c`: {
                                `d`: {
                                    `e`: 4
                                }
                            }
                        }
                    }        
                }"
                          .Replace("`", "\"");
            JsonElement data = JsonDocument.Parse(json).RootElement;

            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("@.a.b.c.d.e == @.b"));

            exp = (exp as ComparisonFilterSubExpression)?.LeftSide as PropertyFilterSubExpression;
            Assert.NotNull(exp);

            JsonElement expected = JsonElementFactory.CreateNumber(4);
            JsonElement result   = exp.Execute(data);

            Assert.Equal(expected, result, JsonElementEqualityComparer.Default);
        }
        public void ValidExpression_ReturnsValidTokens()
        {
            string input = "@.price >= 0 && (@.name.first.contains('a') || @['name'].contains(5) || [email protected])";

            IReadOnlyList <FilterExpressionToken> tokens = FilterExpressionTokenizer.Tokenize(input);

            Assert.Equal(12, tokens.Count);

            Assert.IsType <PropertyExpressionToken>(tokens[0]);
            Assert.IsType <ComparisonOperatorExpressionToken>(tokens[1]);
            Assert.IsType <ConstantNumberExpressionToken>(tokens[2]);
            Assert.IsType <LogicalBinaryOperatorExpressionToken>(tokens[3]);
            Assert.IsType <OpenGroupToken>(tokens[4]);

            Assert.IsType <MethodCallExpressionToken>(tokens[5]);
            MethodCallExpressionToken mct = tokens[5] as MethodCallExpressionToken;

            Assert.Single(mct.Arguments);
            Assert.IsType <ConstantStringExpressionToken>(mct.Arguments.Single());
            Assert.Equal("a", (mct.Arguments.Single() as ConstantStringExpressionToken).StringValue);

            Assert.IsType <LogicalBinaryOperatorExpressionToken>(tokens[6]);
            Assert.IsType <MethodCallExpressionToken>(tokens[7]);
            Assert.IsType <LogicalBinaryOperatorExpressionToken>(tokens[8]);
            Assert.IsType <NegationExpressionToken>(tokens[9]);
            Assert.IsType <PropertyExpressionToken>(tokens[10]);
            Assert.IsType <CloseGroupToken>(tokens[11]);
        }
Example #4
0
        public void TokensWithTruthyElementAccess_Parse_ReturnsCorrectExpression()
        {
            string input = "@.items >= 3 || @.b[123]";
            IReadOnlyList <FilterExpressionToken> tokens = FilterExpressionTokenizer.Tokenize(input);
            FilterSubExpression expr = FilterParser.Parse(tokens);

            Assert.IsType <LogicalFilterSubExpression>(expr);
            LogicalFilterSubExpression logical = expr as LogicalFilterSubExpression;

            // @.items > 3
            Assert.IsType <ComparisonFilterSubExpression>(logical.LeftSide);
            ComparisonFilterSubExpression left = logical.LeftSide as ComparisonFilterSubExpression;

            Assert.True(left.IsGreaterOrEqual);
            Assert.True(left.LeftSide is PropertyFilterSubExpression p1 && p1.PropertyChain.Length == 1 && p1.PropertyChain[0] == "items");
            Assert.True(left.RightSide is NumberConstantFilterSubExpression n1 && n1.Value == 3.0);

            // @.b[0]
            Assert.IsType <TruthyFilterSubExpression>(logical.RightSide);
            TruthyFilterSubExpression tr = logical.RightSide as TruthyFilterSubExpression;

            Assert.IsType <ArrayAccessFilterSubExpression>(tr.Expression);
            ArrayAccessFilterSubExpression ar = tr.Expression as ArrayAccessFilterSubExpression;

            Assert.True(ar.ExactElementsAccess != null && ar.ExactElementsAccess.Length == 1 && ar.ExactElementsAccess[0] == 123);
        }
        public void ExpressionWithMethodCallWithMultipleArguments_ReturnsValidTokens()
        {
            string input = "'a'.ToUpper('abc', 123, true, @.CallingMethod())";
            IReadOnlyList <FilterExpressionToken> tokens = FilterExpressionTokenizer.Tokenize(input);

            Assert.Single(tokens);
            Assert.IsType <MethodCallExpressionToken>(tokens.Single());

            MethodCallExpressionToken mct = tokens.Single() as MethodCallExpressionToken;

            Assert.IsType <ConstantStringExpressionToken>(mct.CalledOnExpression);
            Assert.Equal(4, mct.Arguments.Length);

            Assert.IsType <ConstantStringExpressionToken>(mct.Arguments[0]);
            Assert.Equal("abc", (mct.Arguments[0] as ConstantStringExpressionToken).StringValue);

            Assert.IsType <ConstantNumberExpressionToken>(mct.Arguments[1]);
            Assert.Equal(123.0, (mct.Arguments[1] as ConstantNumberExpressionToken).Token.NumberValue, 6);

            Assert.IsType <ConstantBoolExpressionToken>(mct.Arguments[2]);
            Assert.True((mct.Arguments[2] as ConstantBoolExpressionToken).Token.BoolValue);

            Assert.IsType <MethodCallExpressionToken>(mct.Arguments[3]);
            MethodCallExpressionToken innerMct = mct.Arguments[3] as MethodCallExpressionToken;

            Assert.IsType <PropertyExpressionToken>(innerMct.CalledOnExpression);
            Assert.Empty((innerMct.CalledOnExpression as PropertyExpressionToken).PropertyChain);
            Assert.Equal("CallingMethod", innerMct.MethodName);
        }
        public void ExpressionWithLogicalOperators_ReturnsTokensOfValidTypes()
        {
            string input = "@.a || (@.b > 3 && @.b <= 5)";
            IReadOnlyList <FilterExpressionToken> tokens = FilterExpressionTokenizer.Tokenize(input);

            Type[] tokenTypes = new[]
            {
                typeof(PropertyExpressionToken),
                typeof(LogicalBinaryOperatorExpressionToken),
                typeof(OpenGroupToken),
                typeof(PropertyExpressionToken),
                typeof(ComparisonOperatorExpressionToken),
                typeof(ConstantNumberExpressionToken),
                typeof(LogicalBinaryOperatorExpressionToken),
                typeof(PropertyExpressionToken),
                typeof(ComparisonOperatorExpressionToken),
                typeof(ConstantNumberExpressionToken),
                typeof(CloseGroupToken)
            };

            Assert.Equal(tokenTypes.Length, tokens.Count);

            for (int i = 0; i < tokens.Count; i++)
            {
                Assert.IsType(tokenTypes[i], tokens[i]);
            }
        }
        public void ExpressionWithNestedMethodCalls_ReturnsValidTokens()
        {
            string input = "@.call(@.a.SubString(@.a.b.GetLength(@.a.c.Something())))";

            IReadOnlyList <FilterExpressionToken> tokens = FilterExpressionTokenizer.Tokenize(input);

            Assert.Single(tokens);
            Assert.IsType <MethodCallExpressionToken>(tokens[0]);

            MethodCallExpressionToken mct = tokens[0] as MethodCallExpressionToken;

            Assert.Single(mct.Arguments);
            Assert.IsType <MethodCallExpressionToken>(mct.Arguments.Single());
            Assert.IsType <PropertyExpressionToken>(mct.CalledOnExpression);

            MethodCallExpressionToken arg = mct.Arguments[0] as MethodCallExpressionToken;

            Assert.Single(arg.Arguments);
            Assert.IsType <MethodCallExpressionToken>(arg.Arguments[0]);
            Assert.IsType <PropertyExpressionToken>(arg.CalledOnExpression);

            MethodCallExpressionToken innerArg = arg.Arguments[0] as MethodCallExpressionToken;

            Assert.Single(innerArg.Arguments);
            Assert.IsType <MethodCallExpressionToken>(innerArg.Arguments[0]);
            Assert.IsType <PropertyExpressionToken>(innerArg.CalledOnExpression);

            MethodCallExpressionToken innerInnerArg = innerArg.Arguments[0] as MethodCallExpressionToken;

            Assert.Empty(innerInnerArg.Arguments);
            Assert.IsType <PropertyExpressionToken>(innerInnerArg.CalledOnExpression);
        }
Example #8
0
        public void StringArrayContainsNumber_ReturnsFalse()
        {
            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("@.array.contains(1)"));

            Assert.IsType <MethodCallFilterSubExpression>(exp);

            JsonElement result = exp.Execute(_stringArrayJson);

            Assert.Equal(JsonValueKind.False, result.ValueKind);
        }
        public void GroupFilterSubExpression_ReturnsCorrectValue()
        {
            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("('Abc')"));

            Assert.IsType <GroupFilterSubExpression>(exp);

            JsonElement result = exp.Execute(_null);

            Assert.Equal(_stringAbc, result, JsonElementEqualityComparer.Default);
        }
        public void ExpressionMethodCallWithMultipleArgs_ReturnsCorrectTokens()
        {
            string input = "'a'.ToUpper0('abc', true, false)";
            IReadOnlyList <FilterExpressionToken> tokens = FilterExpressionTokenizer.Tokenize(input);

            Assert.Equal(3, (tokens.Single() as MethodCallExpressionToken).Arguments.Length);

            input  = "'a'.ToUpper0('abc', true, false, 1, 2, 3.3, 4)";
            tokens = FilterExpressionTokenizer.Tokenize(input);
            Assert.Equal(7, (tokens.Single() as MethodCallExpressionToken).Arguments.Length);
        }
Example #11
0
        public void StringContainsOverride_ReturnsCorrectResult(string value, bool caseSensitive, bool expected)
        {
            string path             = $"@.test.contains('{value}', {caseSensitive})";
            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize(path));

            Assert.IsType <MethodCallFilterSubExpression>(exp);

            JsonElement   result         = exp.Execute(_stringJson);
            JsonValueKind expectedResult = expected ? JsonValueKind.True : JsonValueKind.False;

            Assert.Equal(expectedResult, result.ValueKind);
        }
Example #12
0
        public void NumberArrayContains_ReturnsCorrectResult(string value, bool expected)
        {
            string path             = $"@.array.contains({value})";
            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize(path));

            Assert.IsType <MethodCallFilterSubExpression>(exp);

            JsonElement result = exp.Execute(_numberArrayJson);

            JsonValueKind expectedResult = expected ? JsonValueKind.True : JsonValueKind.False;

            Assert.Equal(expectedResult, result.ValueKind);
        }
        public void PropertyFilterSubExpression_RecursionOnObject_ReturnsCorrectValue()
        {
            string json = @"
                {
                    `x`: {
                        `y`: {
                            `a`: 1,
                            `b`: 2,
                            `c`: 3
                        }
                    },
                    `z`: 123
                }
                ".Replace("`", "\"");

            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("@.. == @.b"));

            exp = (exp as ComparisonFilterSubExpression)?.LeftSide as PropertyFilterSubExpression;
            Assert.NotNull(exp);

            string expectedJson = @"
                [
                  {
                    `x`: {
                      `y`: {
                        `a`: 1,
                        `b`: 2,
                        `c`: 3
                      }
                    },
                    `z`: 123
                  },
                  {
                    `y`: {
                      `a`: 1,
                      `b`: 2,
                      `c`: 3
                    }
                  },
                  {
                    `a`: 1,
                    `b`: 2,
                    `c`: 3
                  }
                ]".Replace("`", "\"").RemoveWhiteSpace();

            JsonElement result     = exp.Execute(JsonDocument.Parse(json).RootElement);
            string      resultJson = JsonSerializer.Serialize(result);

            Assert.Equal(expectedJson, resultJson);
        }
Example #14
0
        public void StringToUpperOrToLower_ReturnsCorrectValue(string methodName)
        {
            string path             = $"@.name.{methodName}()";
            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize(path));

            Assert.IsType <MethodCallFilterSubExpression>(exp);

            JsonElement result = exp.Execute(_stringNameJson);
            string      actual = result.GetString();

            string expected = methodName.Contains("pper") ? "KOVALSKI" : "kovalski";

            Assert.Equal(expected, actual);
        }
        public void PropertyFilterSubExpression_LengthOnArray_ReturnsCorrectValue()
        {
            string      json = "{ \"a\": [ \"abc\" ] }";
            JsonElement data = JsonDocument.Parse(json).RootElement;

            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("@.a.length == @.b"));

            exp = (exp as ComparisonFilterSubExpression)?.LeftSide as PropertyFilterSubExpression;
            Assert.NotNull(exp);

            JsonElement expected = JsonElementFactory.CreateNumber(1);
            JsonElement result   = exp.Execute(data);

            Assert.Equal(expected, result, JsonElementEqualityComparer.Default);
        }
        public void BooleanConstantFilterSubExpression_ReturnsCorrectValue()
        {
            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("true"));

            Assert.IsType <BooleanConstantFilterSubExpression>(exp);

            JsonElement result = exp.Execute(_null);

            Assert.Equal(_true, result, JsonElementEqualityComparer.Default);

            exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("false"));
            Assert.IsType <BooleanConstantFilterSubExpression>(exp);

            result = exp.Execute(_null);
            Assert.Equal(_false, result, JsonElementEqualityComparer.Default);
        }
        public void NegationFilterSubExpression_ReturnsCorrectValue()
        {
            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("!('Abc')"));

            Assert.IsType <NegationFilterSubExpression>(exp);

            JsonElement result = exp.Execute(_null);

            Assert.Equal(_false, result);

            exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("!('')"));
            Assert.IsType <NegationFilterSubExpression>(exp);

            result = exp.Execute(_null);
            Assert.Equal(_true, result);
        }
Example #18
0
        public void TokensWithNegation_Parse_ReturnsCorrectExpression()
        {
            string input = "[email protected]";
            IReadOnlyList <FilterExpressionToken> tokens = FilterExpressionTokenizer.Tokenize(input);
            FilterSubExpression expr = FilterParser.Parse(tokens);

            Assert.IsType <NegationFilterSubExpression>(expr);
            NegationFilterSubExpression neg = expr as NegationFilterSubExpression;

            Assert.IsType <TruthyFilterSubExpression>(neg.Expression);
            TruthyFilterSubExpression   truthy = neg.Expression as TruthyFilterSubExpression;
            PropertyFilterSubExpression prop   = truthy.Expression as PropertyFilterSubExpression;

            Assert.True(prop != null && prop.PropertyChain.Length == 2 &&
                        prop.PropertyChain[0] == "price" && prop.PropertyChain[1] == "count");
        }
        public void ExpressionWithMethodCallOnStringConstant_ReturnsValidTokens()
        {
            string input = "'a'.ToUpper() == 'A'";
            IReadOnlyList <FilterExpressionToken> tokens = FilterExpressionTokenizer.Tokenize(input);

            Assert.Equal(3, tokens.Count);
            Assert.IsType <MethodCallExpressionToken>(tokens[0]);

            MethodCallExpressionToken mct = tokens[0] as MethodCallExpressionToken;

            Assert.Empty(mct.Arguments);
            Assert.IsType <ConstantStringExpressionToken>(mct.CalledOnExpression);
            ConstantStringExpressionToken constant = mct.CalledOnExpression as ConstantStringExpressionToken;

            Assert.Equal("a", constant.StringValue);
        }
        public void ExpressionWithMethodCallOnRoot_HasEmptyPropertyChain()
        {
            string input = "@.Something()";
            IReadOnlyList <FilterExpressionToken> tokens = FilterExpressionTokenizer.Tokenize(input);

            Assert.Single(tokens);
            Assert.IsType <MethodCallExpressionToken>(tokens.Single());
            MethodCallExpressionToken mct = tokens.Single() as MethodCallExpressionToken;

            Assert.Equal("Something", mct.MethodName);
            Assert.Empty(mct.Arguments);
            Assert.IsType <PropertyExpressionToken>(mct.CalledOnExpression);
            PropertyExpressionToken callee = mct.CalledOnExpression as PropertyExpressionToken;

            Assert.Empty(callee.PropertyChain);
        }
Example #21
0
        public void TokensWithArray_Parse_ReturnsCorrectExpression()
        {
            string input = "@.items[2] > 3";
            IReadOnlyList <FilterExpressionToken> tokens = FilterExpressionTokenizer.Tokenize(input);
            FilterSubExpression expr = FilterParser.Parse(tokens);

            Assert.IsType <ComparisonFilterSubExpression>(expr);
            ComparisonFilterSubExpression comp = expr as ComparisonFilterSubExpression;

            Assert.IsType <ArrayAccessFilterSubExpression>(comp.LeftSide);
            Assert.True((comp.RightSide as NumberConstantFilterSubExpression)?.Value == 3.0);

            ArrayAccessFilterSubExpression aa = comp.LeftSide as ArrayAccessFilterSubExpression;

            Assert.True(aa.ExactElementsAccess?.Length == 1 && aa.ExactElementsAccess[0] == 2);
            Assert.True(aa.ExecutedOn is PropertyFilterSubExpression p && p.PropertyChain.Length == 1 && p.PropertyChain[0] == "items");
        }
Example #22
0
        public void TokensWithEscapedPropAccess_Parse_ReturnsCorrectExpression()
        {
            string input = "@.items['2'] > 3";
            IReadOnlyList <FilterExpressionToken> tokens = FilterExpressionTokenizer.Tokenize(input);
            FilterSubExpression expr = FilterParser.Parse(tokens);

            Assert.IsType <ComparisonFilterSubExpression>(expr);
            ComparisonFilterSubExpression comp = expr as ComparisonFilterSubExpression;

            Assert.IsType <PropertyFilterSubExpression>(comp.LeftSide);
            Assert.True((comp.RightSide as NumberConstantFilterSubExpression)?.Value == 3.0);

            PropertyFilterSubExpression aa = comp.LeftSide as PropertyFilterSubExpression;

            Assert.Equal(2, aa.PropertyChain.Length);
            Assert.Equal("items", aa.PropertyChain[0]);
            Assert.Equal("2", aa.PropertyChain[1]);
        }
        public void ArrayAccessFilterSubExpression_Slice_ReturnsCorrectValue()
        {
            string json = @"
                {
                    `x`: [ `a`, `b`, `c`, `d`, `e`, `f`, `g`, `h`, `i` ]
                }
                ".Replace("`", "\"");

            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("@.x[0:7:2] == @.b"));

            exp = (exp as ComparisonFilterSubExpression)?.LeftSide as ArrayAccessFilterSubExpression;
            Assert.NotNull(exp);

            JsonElement data   = JsonDocument.Parse(json).RootElement;
            JsonElement result = exp.Execute(data);

            AssertArraysEqual(result, "a", "c", "e", "g");
        }
        public void StringConstantFilterSubExpression_ReturnsCorrectValue()
        {
            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("'Abc'"));

            Assert.IsType <StringConstantFilterSubExpression>(exp);

            JsonElement result = exp.Execute(_null);

            Assert.Equal(_stringAbc, result, JsonElementEqualityComparer.Default);
            Assert.NotEqual(_stringX123, result, JsonElementEqualityComparer.Default);

            exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("\"x123\""));
            Assert.IsType <StringConstantFilterSubExpression>(exp);

            result = exp.Execute(_null);
            Assert.Equal(_stringX123, result, JsonElementEqualityComparer.Default);
            Assert.NotEqual(_stringAbc, result, JsonElementEqualityComparer.Default);
        }
        public void TruthyFilterSubExpression_ReturnsCorrectValue()
        {
            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("true || @.b"));

            Assert.IsType <LogicalFilterSubExpression>(exp);

            FilterSubExpression truthy = ((LogicalFilterSubExpression)exp).RightSide;

            Assert.IsType <TruthyFilterSubExpression>(truthy);

            JsonElement data   = JsonDocument.Parse("{ \"b\" : 3 }").RootElement;
            JsonElement result = truthy.Execute(data);

            Assert.Equal(_true, result);

            data   = JsonDocument.Parse("{ \"b\" : 0 }").RootElement;
            result = truthy.Execute(data);
            Assert.Equal(_false, result);
        }
        public void ExpressionWithArrayAccess_ReturnsValidTokens()
        {
            string input = "@.a[0, 1, 2] > 1 || @.b[2:90:3]";
            IReadOnlyList <FilterExpressionToken> tokens = FilterExpressionTokenizer.Tokenize(input);

            Assert.Equal(5, tokens.Count);

            Assert.IsType <ArrayAccessExpressionToken>(tokens[0]);
            ArrayAccessExpressionToken aa1 = tokens[0] as ArrayAccessExpressionToken;

            Assert.IsType <PropertyExpressionToken>(aa1.ExecutedOn);
            Assert.Equal("a", (aa1.ExecutedOn as PropertyExpressionToken).PropertyChain.Single().StringValue);
            Assert.Equal("0,1,2", aa1.GetIndexValues());

            Assert.IsType <ArrayAccessExpressionToken>(tokens.Last());
            ArrayAccessExpressionToken aa2 = tokens.Last() as ArrayAccessExpressionToken;

            Assert.Equal("b", (aa2.ExecutedOn as PropertyExpressionToken).PropertyChain.Single().StringValue);
            Assert.Equal("2:90:3", aa2.GetIndexValues());
        }
        public void ComparisonLessOrEqual_ReturnsCorrectValue(string json, bool expected)
        {
            json = json.Replace("`", "\"");
            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("@.a <= @.b"));

            Assert.IsType <ComparisonFilterSubExpression>(exp);
            Assert.True(((ComparisonFilterSubExpression)exp).IsLessOrEqual);

            JsonElement data   = JsonDocument.Parse(json).RootElement;
            JsonElement result = exp.Execute(data);

            if (expected)
            {
                Assert.Equal(_true, result);
            }
            else
            {
                Assert.Equal(_false, result);
            }
        }
        public void PropertyFilterSubExpression_WildcardOnObject_ReturnsCorrectValue()
        {
            string json = @"
                {
                    `x`: {
                        `y`: {
                            `z`: [`1`, `2`, `3`]
                        }
                    }
                }
                ".Replace("`", "\"");

            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("@.x.y.z.* == @.b"));

            exp = (exp as ComparisonFilterSubExpression)?.LeftSide as PropertyFilterSubExpression;
            Assert.NotNull(exp);

            JsonElement result = exp.Execute(JsonDocument.Parse(json).RootElement);

            AssertArraysEqual(result, "1", "2", "3");
        }
        public void ExpressionWithMethodCallWithMixedArgs_ReturnsValidTokens()
        {
            string input = "@.a.c.Call1(@.call2(123, false).call3(), true)";

            IReadOnlyList <FilterExpressionToken> tokens = FilterExpressionTokenizer.Tokenize(input);

            Assert.Single(tokens);
            Assert.IsType <MethodCallExpressionToken>(tokens.Single());

            MethodCallExpressionToken call1 = tokens.Single() as MethodCallExpressionToken;

            Assert.IsType <PropertyExpressionToken>(call1.CalledOnExpression);
            PropertyExpressionToken prop1 = call1.CalledOnExpression as PropertyExpressionToken;

            Assert.Equal(2, prop1.PropertyChain.Length);
            Assert.Equal("a", prop1.PropertyChain[0].StringValue);
            Assert.Equal("c", prop1.PropertyChain[1].StringValue);
            Assert.Equal("Call1", call1.MethodName);

            Assert.Equal(2, call1.Arguments.Length);
            Assert.IsType <ConstantBoolExpressionToken>(call1.Arguments.Last());
            Assert.True(call1.Arguments.Last() is ConstantBoolExpressionToken cbt && cbt.Token.BoolValue);

            Assert.IsType <MethodCallExpressionToken>(call1.Arguments.First());
            MethodCallExpressionToken call3 = call1.Arguments.First() as MethodCallExpressionToken;

            Assert.Equal("call3", call3.MethodName);
            Assert.Empty(call3.Arguments);

            Assert.IsType <MethodCallExpressionToken>(call3.CalledOnExpression);
            MethodCallExpressionToken call2 = call3.CalledOnExpression as MethodCallExpressionToken;

            Assert.Equal("call2", call2.MethodName);
            Assert.IsType <PropertyExpressionToken>(call2.CalledOnExpression);
            Assert.Empty((call2.CalledOnExpression as PropertyExpressionToken).PropertyChain);
            Assert.Equal(2, call2.Arguments.Length);

            Assert.True(call2.Arguments[0] is ConstantNumberExpressionToken arg1 && arg1.Token.NumberValue == 123.0);
            Assert.True(call2.Arguments[1] is ConstantBoolExpressionToken arg2 && !arg2.Token.BoolValue);
        }
        public void NumberConstantFilterSubExpression_ReturnsCorrectValue()
        {
            FilterSubExpression exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("1.22"));

            Assert.IsType <NumberConstantFilterSubExpression>(exp);

            JsonElement result = exp.Execute(_null);

            Assert.Equal(_number1_22, result, JsonElementEqualityComparer.Default);

            exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("3344"));
            Assert.IsType <NumberConstantFilterSubExpression>(exp);

            result = exp.Execute(_null);
            Assert.Equal(_number3344, result, JsonElementEqualityComparer.Default);

            exp = FilterParser.Parse(FilterExpressionTokenizer.Tokenize("-44"));
            Assert.IsType <NumberConstantFilterSubExpression>(exp);

            result = exp.Execute(_null);
            Assert.Equal(_numberNegative44, result, JsonElementEqualityComparer.Default);
        }