public void MultipleSelectManyProjectionWorks()
        {
            Reset();

            var dataQuery = TestableThing.MakeQuery(5);

            IQueryable <Tuple <string, string, string> > SelectMany(IQueryable <TestableThing> query) =>
            query.SelectMany(t => t.ChildThings, (t, c) => new
            {
                parentId = t.Id,
                childId  = c.Id,
                children = c.ChildThings
            }).SelectMany(tc => tc.children, (tc, tcc) => new
            {
                tc.parentId,
                tc.childId,
                grandChildId = tcc.Id
            }).Select(t => Tuple.Create(t.parentId, t.childId, t.grandChildId));

            var query = SelectMany(IQueryableExtensions.CreateQueryTemplate <TestableThing>());

            var json = Serializer.Serialize(query);

            // make sure we're not just pulling from the cache
            Reset();

            var newQuery = Serializer.DeserializeQuery <Tuple <string, string, string> >(json, dataQuery);

            var expected = SelectMany(dataQuery).ToList();
            var actual   = newQuery.ToList();

            Assert.NotNull(actual);
            Assert.Equal(expected, actual);
        }
        public void GivenQueryWhenSerializeCalledThenShouldDeserialize(
            IQueryable query,
            Queries type)
        {
            var json = Serializer.Serialize(query);

            // make sure we're not just pulling from the cache
            Reset();

            IQueryable queryHost = TestableThing.MakeQuery(10);

            var newQuery = Serializer.DeserializeQuery(queryHost, json);

            // can't do equivalency check for anonymous types
            if (!query.AsEnumerableExpression().OfType <NewExpression>()
                .Any(t => t.Type.IsAnonymousType()))
            {
                Assert.True(query.IsEquivalentTo(newQuery));
            }

            if (newQuery is IQueryable <ExpandoObject> anonymousQuery)
            {
                var list = anonymousQuery.ToList();
                Assert.NotNull(list);
            }
            else if (newQuery is IQueryable <TestableThing> thingQuery)
            {
                var list = thingQuery.ToList();
                ValidateQuery(list, type);
            }
        }
        public void GivenLambdaWithAnonymousReturnTypeWhenTransformCalledThenShouldReturnExpression(LambdaExpression lambda)
        {
            var actual = adapter.TransformLambda(lambda);

            Assert.NotSame(lambda, actual);
            object source, target;

            if (lambda.Parameters.Any())
            {
                var thing = new TestableThing();
                target = actual.Compile().DynamicInvoke(thing);
                source = lambda.Compile().DynamicInvoke(thing);
            }
            else
            {
                target = actual.Compile().DynamicInvoke(null);
                source = lambda.Compile().DynamicInvoke(null);
            }

            object targetVal;

            if (lambda.AsEnumerable().OfType <NewExpression>().Any())
            {
                Assert.IsType <AnonInitializer>(target);
                targetVal = (target as AnonInitializer).AnonValue.GetValue();
            }
            else
            {
                targetVal = target;
            }

            Assert.True(ExpressionEquivalency.ValuesAreEquivalent(source, targetVal));
        }
        public void GivenDefaultConfigurationWhenNoConfigProvidedThenShouldUseDefault(bool configOverride)
        {
            var query = TestableThing.MakeQuery().Where(t => t.Id.Contains("aa") && (t.IsActive || t.Value < int.MaxValue / 2));

            Serializer.ConfigureDefaults(config => config.WithJsonSerializerOptions(
                                             new JsonSerializerOptions
            {
                IgnoreNullValues         = false,
                IgnoreReadOnlyProperties = true
            }).Configure());

            if (configOverride)
            {
                var json = Serializer.Serialize(query, config => config.CompressTypes(false).Configure());
                Assert.DoesNotContain("null", json);
                Assert.DoesNotContain("^", json);

                Reset();

                var expr = Serializer.DeserializeQuery <TestableThing>(json, config: config => config.CompressTypes(false).Configure());
                Assert.True(query.IsEquivalentTo(expr));
            }
            else
            {
                var json = Serializer.Serialize(query);
                Assert.Contains("null", json);
                // Assert.Contains("^", json);
            }

            Serializer.ConfigureDefaults(config => config.Configure());
        }
        public void GivenQueryWhenSerializeCalledThenShouldDeserialize(
            IQueryable query,
            Queries type)
        {
            var json = Serializer.Serialize(query);

            // make sure we're not just pulling from the cache
            Reset();

            rulesConfig.Value.RuleForType <TestableThing>()
            .RuleForType <SerializerTests>();

            IQueryable queryHost = TestableThing.MakeQuery(100);

            var newQuery = Serializer.DeserializeQuery(queryHost, json);

            // can't do equivalency check for anonymous types
            if (!query.AsEnumerableExpression().OfType <NewExpression>().Any(t => t.Type.IsAnonymousType()))
            {
                Assert.True(query.IsEquivalentTo(newQuery));
            }
            var testRun = newQuery.AsObjectArray(); // ensure it runs

            Assert.NotNull(testRun);
            if (newQuery is IQueryable <TestableThing> thingQuery)
            {
                var list = thingQuery.ToList();
                ValidateQuery(list, type);
            }
        }
        public void GivenNestedMethodsThenWillCompress()
        {
            var str        = "aa ";
            var query      = TestableThing.MakeQuery().Where(t => t.Id.Contains(str.Trim()));
            var expression = target.EvalAndCompress(query.Expression);

            Assert.Contains(expression.AsEnumerable().ConstantsOfType <string>(), ce => ce.Value.ToString() == str.Trim());
        }
        public void GivenFilterWithVariableWhenVisitedThenExtractsValues()
        {
            var isActive   = true;
            var query      = TestableThing.MakeQuery().Where(t => t.IsActive == isActive);
            var expression = target.EvalAndCompress(query.Expression);

            Assert.Contains(expression.AsEnumerable().OfType <ConstantExpression>(), ce => ce.Type == typeof(bool) && (bool)ce.Value == true);
        }
        public void GivenExpressionThatCanResolveWhenVisitedThenExtractsValues()
        {
            var x          = 2;
            var y          = 3;
            var query      = TestableThing.MakeQuery().Where(t => (x < y) ? t.IsActive : !t.IsActive);
            var expression = target.EvalAndCompress(query.Expression);

            Assert.DoesNotContain(expression.AsEnumerable(), ex => ex is ConditionalExpression);
        }
        public void GivenExpressionAgainstStringAndDateWhenVisitedWillCompress()
        {
            var days  = 5;
            var str   = "aa";
            var query = TestableThing.MakeQuery().Where(t => t.Created > DateTime.Now.AddDays(-1 * days) &&
                                                        t.Id.Contains(str));
            var expression = target.EvalAndCompress(query.Expression);

            Assert.Contains(expression.AsEnumerable().ConstantsOfType <string>(), ce => ce.Value.ToString() == str);
        }
        public void GivenSkipOrTakeWithVariableWhenVisitedThenExtractsConstants()
        {
            var skip       = 1;
            var take       = 2;
            var query      = TestableThing.MakeQuery().Skip(skip).Take(take);
            var expression = target.EvalAndCompress(query.Expression);

            Assert.Contains(expression.AsEnumerable().OfType <ConstantExpression>(), ce => ce.Type == typeof(int) && (int)ce.Value == skip);
            Assert.Contains(expression.AsEnumerable().OfType <ConstantExpression>(), ce => ce.Type == typeof(int) && (int)ce.Value == take);
        }
        public void GivenObjectWhenLambdaExpressionThatReferencesPropertyIsDeserializedThenShouldResolveProperty()
        {
            var things = TestableThing.MakeQuery(2).ToList();
            Expression <Func <List <TestableThing>, string> > firstId =
                list => list.First().Id;
            var serialized   = TestSerializer.GetSerializedFragment <Lambda, LambdaExpression>(firstId);
            var deserialized = lambdaSerializer.Deserialize(serialized, new SerializationState());
            var expected     = firstId.Compile()(things);
            var actual       = deserialized.Compile().DynamicInvoke(things);

            Assert.Equal(expected, actual);
        }
        public void GivenQueryCanSerializeAndDeserialize(IQueryable query, QueryExprSerializerTests.Queries queryType)
        {
            var root             = QueryExprSerializer.Serialize(query, config => config.CompressExpressionTree(false));
            var json             = wrapper.FromSerializationRoot(root);
            var deserializedRoot = wrapper.ToSerializationRoot(json);

            Assert.NotNull(deserializedRoot);
            IQueryable queryHost         = TestableThing.MakeQuery(10);
            var        deserializedQuery = QueryExprSerializer.DeserializeQuery(queryHost, deserializedRoot);

            Assert.NotNull(deserializedQuery);
            Assert.True(query.Expression.IsEquivalentTo(deserializedQuery.Expression));
        }
        public static IEnumerable <object[]> GetQueryMatrix()
        {
            yield return(new object[]
            {
                TestableThing.MakeQuery().Skip(1).Take(1),
                Queries.Skip1Take1
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().OrderBy(t => t.Created).ThenByDescending(t => t.Id),
                Queries.OrderByCreatedThenByDescendingId
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().Where(t => t.Id.Contains("aa")),
                Queries.WhereIdContainsAA
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().Where(t => Property <int>(t, nameof(TestableThing.Value)) > 500),
                Queries.CustomGenericProperty
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().Select(t => t.Id),
                Queries.IdProjection
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().Select(t => new { t.Id }),
                Queries.IdAnonymousType
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().OrderBy(t => t.Id).Select(t => new TestableThing(t.Id)),
                Queries.IdOnly
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().Where(t => t.Id.Contains("aa") && (t.IsActive || t.Value < int.MaxValue / 2)),
                Queries.Filtered
            });
        }
        public void GivenQueryWhenSerializeCalledThenShouldDeserializeForType(
            IQueryable <TestableThing> query,
            Queries type)
        {
            var json = Serializer.Serialize(query);

            Reset();

            var queryHost = TestableThing.MakeQuery(100);
            var newQuery  = Serializer.DeserializeQuery <TestableThing>(json, queryHost);

            Assert.True(query.IsEquivalentTo(newQuery));
            ValidateQuery(newQuery.ToList(), type);
        }
        public void GivenNewExpressionWithAnonymousTypeAndReferenceWhenTransformNewCalledThenShouldReturnTransformedExpression()
        {
            var thing      = new TestableThing();
            var query      = new List <TestableThing>().AsQueryable();
            var projection = query.Select(t => new { t.Id });
            var exprNew    = projection.Expression.AsEnumerable().OfType <NewExpression>().Single();
            var parameters = projection.Expression.AsEnumerable().OfType <LambdaExpression>()
                             .Single().Parameters;
            var transformed = adapter.TransformNew(exprNew);

            Assert.Equal(typeof(AnonInitializer), transformed.Type);
            var originalNew    = Expression.Lambda <Func <TestableThing, object> >(exprNew, parameters);
            var originalObj    = originalNew.Compile()(thing);
            var transformedNew = Expression.Lambda <Func <TestableThing, AnonInitializer> >(transformed, parameters);
            var transformedObj = transformedNew.Compile()(thing).AnonValue.GetValue();

            Assert.True(ExpressionEquivalency.ValuesAreEquivalent(originalObj, transformedObj));
        }
 public void GivenConditionalIfTestCanBeEvaluatedThenShouldTransformToTestResult(int scenario)
 {
     if (scenario == 0 || scenario == 1)
     {
         var x        = scenario == 0 ? 2 : 3;
         var expected = scenario == 0 ? 0 : 1;
         Expression <Func <int> > expr = () => x % 2 == 0 ? 0 : 1;
         var compiled = target.EvalAndCompress(expr);
         Assert.False(compiled.AsEnumerable().OfType <ConditionalExpression>().Any());
         var actual = ((Func <int>)((ConstantExpression)compiled).Value)();
         Assert.Equal(expected, actual);
     }
     else
     {
         var query         = TestableThing.MakeQuery().Select(t => t.Created < DateTime.Now.AddDays(-7) ? 0 : 1);
         var compiledQuery = target.EvalAndCompress(query.Expression);
         Assert.True(compiledQuery.AsEnumerable().OfType <ConditionalExpression>().Any());
     }
 }
        public void GivenConvertedLambdaWhenTransformCalledThenShouldReturnExpression(LambdaExpression lambda)
        {
            var    transformed = adapter.TransformLambda(lambda);
            var    actual = adapter.TransformLambda(transformed);
            object source, target;

            if (lambda.Parameters.Any())
            {
                var thing = new TestableThing();
                target = actual.Compile().DynamicInvoke(thing);
                source = lambda.Compile().DynamicInvoke(thing);
            }
            else
            {
                target = actual.Compile().DynamicInvoke(null);
                source = lambda.Compile().DynamicInvoke(null);
            }

            Assert.True(ExpressionEquivalency.ValuesAreEquivalent(source, target));
        }
        public void GroupByWorks()
        {
            Reset();

            var dataQuery = TestableThing.MakeQuery(10);
        public static IEnumerable <object[]> GetQueryMatrix()
        {
            yield return(new object[]
            {
                TestableThing.MakeQuery().Select(t => new { t.Id }),
                Queries.IdAnonymousType
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().SelectMany(t => t.ChildThings),
                Queries.SelectMany
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().Where(t => t.ChildThings.Count > 2).Select(t => new TestableThing(t.Id)
                {
                    ChildThings =
                    {
                        new TestableThing {
                            Id = Guid.NewGuid().ToString()
                        },
                        new TestableThing {
                            Id = t.ChildThings[0].Id
                        }
                    }
                }),
                Queries.MemberInit
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().Skip(1).Take(1),
                Queries.Skip1Take1
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().OrderBy(t => t.Created).ThenByDescending(t => t.Id),
                Queries.OrderByCreatedThenByDescendingId
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().Where(t => t.Id.Contains("aa")),
                Queries.WhereIdContainsAA
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().Where(t => Property <int>(t, nameof(TestableThing.Value)) > 500),
                Queries.CustomGenericProperty
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().Select(t => t.Id),
                Queries.IdProjection
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().OrderBy(t => t.Id).Select(t => new TestableThing(t.Id)),
                Queries.IdOnly
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().Where(t => t.Id.Contains("aa") && (t.IsActive || t.Value < int.MaxValue / 2)),
                Queries.Filtered
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().Where(t => t.Id.Contains("aa")).Select(t => new TestableThing {
                    Id = t.Id
                }),
                Queries.MemberInit
            });

            yield return(new object[]
            {
                TestableThing.MakeQuery().Select(t => new TestableThing(t.Id)
                {
                    Data = { Data = t.ChildThings.Count.ToString() }
                }),
                Queries.MemberInit
            });
        }
 public void WhenDeserializeQueryForTypeCalledWithEmptyOrNullJsonThenShouldThrowArgument(string json)
 {
     Assert.Throws <ArgumentException>(() =>
                                       Serializer.DeserializeQuery(TestableThing.MakeQuery(), json));
 }
 public static IEnumerable <object[]> GetAndMatrix()
 {
     var core = TestableThing.MakeQuery();
     Expression <Func <bool> > eval = () => DateTime.Now.Ticks < 12;