public void TestReduceAll()
        {
            RunTestVariants(() => {
                CreateIndex();

                var options      = C4QueryOptions.Default;
                var context      = new CountContext();
                var reduce       = new C4ManagedReduceFunction(CountAccumulate, CountReduce, context);
                var reduceNative = reduce.Native;
                options.reduce   = &reduceNative;

                var e = (C4QueryEnumerator *)LiteCoreBridge.Check(err => {
                    var localOpts = options;
                    return(Native.c4view_query(_view, &localOpts, err));
                });

                // First row:
                C4Error error;
                Native.c4queryenum_next(e, &error).Should().BeTrue("because otherwise the query failed");
                var valueStr = e->value.CreateString();
                Console.WriteLine($"Key: {Native.c4key_toJSON(&e->key)} Value: {valueStr}");
                Native.c4key_toJSON(&e->key).Should().BeNull("because the reduce has no key");
                valueStr.Should().Be("200", "because the reduce function should return the proper value");

                // No more rows:
                Native.c4queryenum_next(e, &error).Should().BeFalse("because the reduce function only contains one row");
                Native.c4queryenum_free(e);
                error.Code.Should().Be(0, "because otherwise an error occurred somewhere");
                ;
            });
        }
        public void TestPerformance()
        {
            var     jsonData = File.ReadAllBytes(JsonFilePath);
            FLError error;
            var     unmanagedData = Marshal.AllocHGlobal(jsonData.Length);

            Marshal.Copy(jsonData, 0, unmanagedData, jsonData.Length);
            var slice      = new FLSlice(unmanagedData.ToPointer(), (ulong)jsonData.Length);
            var fleeceData = NativeRaw.FLData_ConvertJSON(slice, &error);
            var root       = Native.FLValue_AsArray(NativeRaw.FLValue_FromData(fleeceData));

            RunTestVariants(() => {
                uint numDocs;
                {
                    var st  = Stopwatch.StartNew();
                    numDocs = InsertDocs(root);
                    numDocs.Should().Be(12188, "because otherwise an incorrect number of documents was inserted");
                    st.PrintReport("Writing docs", numDocs, "doc");
                }
                {
                    var st = Stopwatch.StartNew();
                    IndexViews();
                    st.PrintReport("Indexing Albums/Artists views", numDocs, "doc");
                }
                {
                    var st = Stopwatch.StartNew();
                    IndexTracksView();
                    st.PrintReport("Indexing Tracks view", numDocs, "doc");
                }
                {
                    var st      = Stopwatch.StartNew();
                    var context = new TotalContext();
                    var reduce  = new C4ManagedReduceFunction(TotalAccumulate, TotalReduce, context);

                    var numArtists = QueryGrouped(_artistsView, reduce.Native);
                    reduce.Dispose();
                    numArtists.Should().Be(1141, "because otherwise the query returned incorrect information");
                    st.PrintReport("Grouped query of Artist view", numDocs, "doc");
                }
            });

            Marshal.FreeHGlobal(unmanagedData);
        }
        public void TestImportNames()
        {
            // Docs look like:
            // {"name":{"first":"Travis","last":"Mutchler"},"gender":"female","birthday":"1990-12-21","contact":{"address":{"street":"22 Kansas Cir","zip":"45384","city":"Wilberforce","state":"OH"},"email":["*****@*****.**","*****@*****.**"],"region":"937","phone":["937-3512486"]},"likes":["travelling"],"memberSince":"2010-01-01"}

            RunTestVariants(() => {
                var numDocs = ImportJSONLines("/Couchbase/example-datasets-master/RandomUsers/names_300000.json",
                                              TimeSpan.FromSeconds(15), true);
                var complete = numDocs == 300000;
                #if !DEBUG
                numDocs.Should().Be(300000, "because otherwise the operation was too slow");
                #endif
                {
                    var st         = Stopwatch.StartNew();
                    var totalLikes = IndexLikesView();
                    Console.WriteLine($"Total of {totalLikes} likes");
                    st.PrintReport("Indexing Likes view", numDocs, "doc");
                    if (complete)
                    {
                        totalLikes.Should().Be(345986, "because otherwise the index missed data set objects");
                    }
                }
                {
                    var st      = Stopwatch.StartNew();
                    var context = new CountContext();
                    using (var reduce = new C4ManagedReduceFunction(CountAccumulate, CountReduce, context)) {
                        var numLikes = QueryGrouped(_likesView, reduce.Native, true);
                        st.PrintReport("Querying all likes", numLikes, "like");
                        if (complete)
                        {
                            numLikes.Should().Be(15, "because that is the number of likes in the data set");
                        }
                    }
                }
                {
                    var st    = Stopwatch.StartNew();
                    var total = IndexStatesView();
                    st.PrintReport("Indexing States view", numDocs, "doc");
                    if (complete)
                    {
                        total.Should().Be(300000, "because otherwise the index missed some dataset objects");
                    }
                }
                {
                    var options = C4QueryOptions.Default;
                    var key     = Native.c4key_new();
                    NativeRaw.c4key_addString(key, C4Slice.Constant("WA"));
                    options.startKey = options.endKey = key;
                    var st           = Stopwatch.StartNew();
                    var total        = RunQuery(_statesView, options);
                    Native.c4key_free(key);
                    st.PrintReport("Querying States view", total, "row");
                    if (complete)
                    {
                        total.Should().Be(5053, "because that is the number of states in the data set");
                    }
                }
                {
                    if (Storage == C4StorageEngine.SQLite && !IsRevTrees())
                    {
                        for (int pass = 0; pass < 2; ++pass)
                        {
                            var st = Stopwatch.StartNew();
                            var n  = QueryWhere("{\"contact.address.state\": \"WA\"}");
                            st.PrintReport("SQL query of state", n, "doc");
                            if (complete)
                            {
                                n.Should().Be(5053, "because that is the number of states in the data set");
                            }
                            if (pass == 0)
                            {
                                var st2 = Stopwatch.StartNew();
                                LiteCoreBridge.Check(err => Native.c4db_createIndex(Db, "contact.address.state", err));
                                st2.PrintReport("Creating SQL index of state", 1, "index");
                            }
                        }
                    }
                }
            });
        }