public void ValidateSQLTranslationComplexData()
        {
            string constString = "s";

            int[] array  = { 1, 2, 3 };
            var   paramx = Expression.Parameter(typeof(int), "x");

            const int Records                    = 100;
            const int MaxArraySize               = 10;
            const int MaxStringLength            = 50;
            Func <Random, complex> createDataObj = (random) =>
            {
                var obj = new complex();
                obj.b        = random.NextDouble() < 0.5;
                obj.dbl      = random.NextDouble();
                obj.dblArray = new double[random.Next(MaxArraySize)];
                for (int i = 0; i < obj.dblArray.Length; ++i)
                {
                    obj.dblArray[i] = random.NextDouble() < 0.1 ? 3 : random.NextDouble();
                }
                obj.inside = new simple()
                {
                    x = random.Next(), y = random.Next()
                };
                obj.str = random.NextDouble() < 0.1 ? "5" : LinqTestsCommon.RandomString(random, random.Next(MaxStringLength));
                obj.id  = Guid.NewGuid().ToString();
                obj.pk  = "Test";
                return(obj);
            };
            var getQuery = LinqTestsCommon.GenerateTestCosmosData <complex>(createDataObj, Records, testContainer);

            var inputs = new List <LinqTestInput>();

            inputs.Add(new LinqTestInput("Select equality", b => getQuery(b).Select(s => s.str == "5")));
            inputs.Add(new LinqTestInput("Select string concat", b => getQuery(b).Select(d => "x" + d.str)));
            inputs.Add(new LinqTestInput("Select string concat w const", b => getQuery(b).Select(d => "x" + constString + d.str)));

            inputs.Add(new LinqTestInput("SelectMany array", b => getQuery(b).SelectMany(d => d.dblArray)));
            inputs.Add(new LinqTestInput("SelectMany array property -> Filter x -> Select x expr", b => getQuery(b).SelectMany(z => z.dblArray).Where(x => x > 2).Select(x => x + 2)));
            inputs.Add(new LinqTestInput("SelectMany array property -> Filter x equality -> Select x expr", b => getQuery(b).SelectMany(z => z.dblArray.Where(x => x == 3).Select(x => x + 1))));
            inputs.Add(new LinqTestInput("SelectMany array property -> Select identity", b => getQuery(b).SelectMany(d => d.dblArray.Select(x => x))));
            inputs.Add(new LinqTestInput("SelectMany array property", b => getQuery(b).SelectMany(d => d.dblArray)));
            inputs.Add(new LinqTestInput("SelectMany array property -> Select x expr", b => getQuery(b).SelectMany(z => z.dblArray.Select(x => z.dbl + x))));
            inputs.Add(new LinqTestInput("SelectMany array property -> Select new", b => getQuery(b).SelectMany(z => z.dblArray.Select(x => new { z.b, x = Math.Truncate(x * 100) }))));

            inputs.Add(new LinqTestInput("SelectMany identity", b => getQuery(b).SelectMany(x => x.dblArray)));
            inputs.Add(new LinqTestInput("SelectMany x -> Select y", b => getQuery(b).SelectMany(x => x.dblArray.Select(y => y))));
            inputs.Add(new LinqTestInput("SelectMany x -> Select x.y", b => getQuery(b).SelectMany(x => x.dblArray.Select(y => y))));
            inputs.Add(new LinqTestInput("SelectMany array", b => getQuery(b).SelectMany(x => x.dblArray)));
            this.ExecuteTestSuite(inputs);
        }
        public static Func <bool, IQueryable <Family> > GenerateFamilyCosmosData(
            Cosmos.Database cosmosDatabase, out Container container)
        {
            // The test collection should have range index on string properties
            // for the orderby tests
            PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition {
                Paths = new System.Collections.ObjectModel.Collection <string>(new[] { "/Pk" }), Kind = PartitionKind.Hash
            };
            var newCol = new ContainerProperties()
            {
                Id             = Guid.NewGuid().ToString(),
                PartitionKey   = partitionKeyDefinition,
                IndexingPolicy = new Microsoft.Azure.Cosmos.IndexingPolicy()
                {
                    IncludedPaths = new Collection <Cosmos.IncludedPath>()
                    {
                        new Cosmos.IncludedPath()
                        {
                            Path    = "/*",
                            Indexes = new System.Collections.ObjectModel.Collection <Microsoft.Azure.Cosmos.Index>()
                            {
                                Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.Number, -1),
                                Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.String, -1)
                            }
                        }
                    },
                    CompositeIndexes = new Collection <Collection <Cosmos.CompositePath> >()
                    {
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending
                            }
                        },
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Descending
                            }
                        },
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Descending
                            }
                        },
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Descending
                            }
                        },
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Descending
                            }
                        }
                    }
                }
            };

            container = cosmosDatabase.CreateContainerAsync(newCol).Result;
            const int Records                   = 100;
            const int MaxNameLength             = 100;
            const int MaxThingStringLength      = 50;
            const int MaxChild                  = 5;
            const int MaxPets                   = MaxChild;
            const int MaxThings                 = MaxChild;
            const int MaxGrade                  = 101;
            const int MaxTransaction            = 20;
            const int MaxTransactionMinuteRange = 200;
            int       MaxTransactionType        = Enum.GetValues(typeof(TransactionType)).Length;

            Family createDataObj(Random random)
            {
                var obj = new Family
                {
                    FamilyId     = random.NextDouble() < 0.05 ? "some id" : Guid.NewGuid().ToString(),
                    IsRegistered = random.NextDouble() < 0.5,
                    NullableInt  = random.NextDouble() < 0.5 ? (int?)random.Next() : null,
                    Int          = random.NextDouble() < 0.5 ? 5 : random.Next(),
                    Id           = Guid.NewGuid().ToString(),
                    Pk           = "Test",
                    Parents      = new Parent[random.Next(2) + 1]
                };

                for (int i = 0; i < obj.Parents.Length; ++i)
                {
                    obj.Parents[i] = new Parent()
                    {
                        FamilyName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)),
                        GivenName  = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength))
                    };
                }

                obj.Tags = new string[random.Next(MaxChild)];
                for (int i = 0; i < obj.Tags.Length; ++i)
                {
                    obj.Tags[i] = (i + random.Next(30, 36)).ToString();
                }

                obj.Children = new Child[random.Next(MaxChild)];
                for (int i = 0; i < obj.Children.Length; ++i)
                {
                    obj.Children[i] = new Child()
                    {
                        Gender     = random.NextDouble() < 0.5 ? "male" : "female",
                        FamilyName = obj.Parents[random.Next(obj.Parents.Length)].FamilyName,
                        GivenName  = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)),
                        Grade      = random.Next(MaxGrade)
                    };

                    obj.Children[i].Pets = new List <Pet>();
                    for (int j = 0; j < random.Next(MaxPets); ++j)
                    {
                        obj.Children[i].Pets.Add(new Pet()
                        {
                            GivenName = random.NextDouble() < 0.5 ?
                                        LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)) :
                                        "Fluffy"
                        });
                    }

                    obj.Children[i].Things = new Dictionary <string, string>();
                    for (int j = 0; j < random.Next(MaxThings) + 1; ++j)
                    {
                        obj.Children[i].Things.Add(
                            j == 0 ? "A" : $"{j}-{random.Next().ToString()}",
                            LinqTestsCommon.RandomString(random, random.Next(MaxThingStringLength)));
                    }
                }

                obj.Records = new Logs
                {
                    LogId        = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)),
                    Transactions = new Transaction[random.Next(MaxTransaction)]
                };
                for (int i = 0; i < obj.Records.Transactions.Length; ++i)
                {
                    var transaction = new Transaction()
                    {
                        Amount = random.Next(),
                        Date   = DateTime.Now.AddMinutes(random.Next(MaxTransactionMinuteRange)),
                        Type   = (TransactionType)(random.Next(MaxTransactionType))
                    };
                    obj.Records.Transactions[i] = transaction;
                }

                return(obj);
            }

            Func <bool, IQueryable <Family> > getQuery = LinqTestsCommon.GenerateTestCosmosData(createDataObj, Records, container);

            return(getQuery);
        }
        public void ValidateSQLTranslation()
        {
            int constInt = 2;

            int[] array      = { 1, 2, 3 };
            var   paramx     = Expression.Parameter(typeof(int), "x");
            float floatValue = 5.23f;

            const int             Records       = 100;
            Func <Random, simple> createDataObj = (random) =>
            {
                var obj = new simple();
                obj.x  = random.Next();
                obj.y  = random.Next();
                obj.id = Guid.NewGuid().ToString();
                obj.pk = "Test";
                return(obj);
            };
            var dataQuery = LinqTestsCommon.GenerateTestCosmosData <simple>(createDataObj, Records, testContainer);

            var inputs = new List <LinqTestInput>();

            inputs.Add(new LinqTestInput("Select cast float", b => dataQuery(b).Select(x => (int)(floatValue))));
            inputs.Add(new LinqTestInput("Select identity", b => dataQuery(b).Select(x => x)));
            inputs.Add(new LinqTestInput("Select int expr", b => dataQuery(b).Select(x => x.x % 10 + 2 + x.x % 5)));
            inputs.Add(new LinqTestInput("Select int expr w const", b => dataQuery(b).Select(x => x.x + constInt)));
            inputs.Add(new LinqTestInput("Select w new array", b => dataQuery(b).Select(d => new int[2] {
                d.x, d.x + 1
            })));
            inputs.Add(new LinqTestInput("Select new", b => dataQuery(b).Select(d => new { first = d.x, second = d.x })));
            inputs.Add(new LinqTestInput("Select nested new", b => dataQuery(b).Select(d => new { first = d.x, second = new { third = d.x } })));
            inputs.Add(new LinqTestInput("Filter int >", b => dataQuery(b).Where(x => x.x > 2)));
            inputs.Add(new LinqTestInput("Filter method >", b => dataQuery(b).Where(x => x.x > id(3))));
            inputs.Add(new LinqTestInput("Filter int > -> Select int expr", b => dataQuery(b).Where(x => x.x > 2).Select(x => x.x + 2)));
            inputs.Add(new LinqTestInput("Select int expr -> Filter int >", b => dataQuery(b).Select(x => x.x + 2).Where(x => x > 2)));
            inputs.Add(new LinqTestInput("Filter int > -> Filter another field", b => dataQuery(b).Where(x => x.x > 2).Where(y => y.x < 4)));
            inputs.Add(new LinqTestInput("Filter x -> Filter y -> Select y expr", b => dataQuery(b).Where(x => x.x > 2).Where(y => y.x < 4).Select(y => y.x + y.x)));
            inputs.Add(new LinqTestInput("Select expr w const array", b => dataQuery(b).Select(x => x.x + array[2])));
            inputs.Add(new LinqTestInput("Select const array index", b => dataQuery(b)
                                         .Where(x => x.x >= 0 && x.x < 3)
                                         .Select(x => new int[] { 1, 2, 3 }[x.x]), "The specified query includes 'member indexer' which is currently not supported."));
            inputs.Add(new LinqTestInput("Select new simple", b => dataQuery(b).Select(x => new simple {
                x = x.x, y = x.x
            })));
            inputs.Add(new LinqTestInput("Select new nested", b => dataQuery(b).Select(x => new nested {
                s = new simple {
                    x = x.x, y = x.x
                }, x = 2
            })));
            inputs.Add(new LinqTestInput("Select new complex", b => dataQuery(b).Select(d => new complex {
                dbl = 1.0, str = "", b = false, dblArray = new double[] { 1.0, 2.0, }, inside = new simple {
                    x = d.x, y = d.x
                }
            })));
            inputs.Add(new LinqTestInput("Select cast double x", b => dataQuery(b).Select(x => (double)x.x)));
            inputs.Add(new LinqTestInput("Select indexer x", b => dataQuery(b)
                                         .Where(x => x.x >= 0 && x.x < array.Length)
                                         .Select(x => array[x.x]), "The specified query includes 'member indexer' which is currently not supported."));
            inputs.Add(new LinqTestInput("Select new constructor", b => dataQuery(b).Select(x => new TimeSpan(x.x)), "Constructor invocation is not supported."));
            inputs.Add(new LinqTestInput("Select method id", b => dataQuery(b).Select(x => id(x)), "Method 'id' is not supported."));
            inputs.Add(new LinqTestInput("Select identity", b => dataQuery(b).Select(x => x)));
            inputs.Add(new LinqTestInput("Select simple property", b => dataQuery(b).Select(x => x.x)));
            this.ExecuteTestSuite(inputs);
        }