Exemplo n.º 1
0
        public void TestQueryObserverWithChangingQueryParameters()
        {
            RunTestVariants(() =>
            {
                var handle = GCHandle.Alloc(this);
                try {
                    Compile(Json5("['=', ['.', 'contact', 'address', 'state'], ['$state']]"));
                    C4Error error;

                    //As part of this, added c4query_setParameters. Parameter values can now be stored with a query as in the CBL API.
                    //Pass null parameters to c4query_run to use the ones stored in the query.
                    Native.c4query_setParameters(_query, "{\"state\": \"CA\"}");

                    var explain = Native.c4query_explain(_query);
                    //CHECK(explain);
                    WriteLine($"Explain = {explain}");

                    _queryObserver = Native.c4queryobs_create(_query, QueryCallback, GCHandle.ToIntPtr(handle).ToPointer());
                    //CHECK(_queryObserver);
                    Native.c4queryobs_setEnabled(_queryObserver, true);

                    WriteLine("---- Waiting for query observers...");
                    Thread.Sleep(2000);

                    WriteLine("Checking query observers...");
                    _queryCallbackCalls.Should().Be(1, "because we should have received a callback");
                    var e1 = (C4QueryEnumerator *)LiteCoreBridge.Check(err =>
                    {
                        return(Native.c4queryobs_getEnumerator(_queryObserver, true, err));
                    });
                    //REQUIRE(e);
                    //CHECK(c4queryobs_getEnumerator(state.obs, true, &error) == nullptr);
                    //CHECK(error.code == 0);
                    Native.c4queryenum_getRowCount(e1, &error).Should().Be(8);

                    Native.c4query_setParameters(_query, "{\"state\": \"NY\"}");

                    WriteLine("---- Waiting for query observers after changing the parameters...");
                    Thread.Sleep(5000);

                    WriteLine("Checking query observers...");
                    _queryCallbackCalls.Should().Be(2, "because we should have received a callback");
                    var e2 = (C4QueryEnumerator *)LiteCoreBridge.Check(err =>
                    {
                        return(Native.c4queryobs_getEnumerator(_queryObserver, true, err));
                    });
                    //REQUIRE(e2);
                    //CHECK(error.code == 0);
                    Native.c4queryenum_getRowCount(e2, &error).Should().Be(9);
                } finally {
                    handle.Free();
                }
            });
        }
Exemplo n.º 2
0
        protected override void TeardownVariant(int option)
        {
            /** Stops an observer and frees the resources it's using.
             *  It is safe to pass NULL to this call. */
            Native.c4queryobs_free(_queryObserver);
            _queryObserver = null;
            Native.c4queryobs_free(_queryObserver2);
            _queryObserver2 = null;
            Native.c4queryobs_free(_queryObserver3);
            _queryObserver3 = null;

            base.TeardownVariant(option);
        }
Exemplo n.º 3
0
 private void QueryObserverCalled(C4QueryObserver *obs, C4Query *query)
 {
     WriteLine("---- Query observer called!");
     if ((long)obs == (long)_queryObserver)
     {
         _queryCallbackCalls++;
     }
     else if ((long)obs == (long)_queryObserver2)
     {
         _queryCallbackCalls2++;
     }
     else if ((long)obs == (long)_queryObserver3)
     {
         _queryCallbackCalls3++;
     }
 }
Exemplo n.º 4
0
        private static void QueryObserverCallback(C4QueryObserver *obs, C4Query *query, void *context)
        {
            var obj = GCHandle.FromIntPtr((IntPtr)context).Target as QueryTest;

            obj.QueryObserverCalled(obs, query);
        }
Exemplo n.º 5
0
        public void TestMultipleQueryObservers()
        {
            RunTestVariants(() =>
            {
                var handle = GCHandle.Alloc(this);
                try {
                    Compile(Json5("['=', ['.', 'contact', 'address', 'state'], 'CA']"));
                    C4Error error;

                    _queryObserver = Native.c4queryobs_create(_query, QueryCallback, GCHandle.ToIntPtr(handle).ToPointer());
                    //CHECK(_queryObserver);
                    Native.c4queryobs_setEnabled(_queryObserver, true);

                    _queryObserver2 = Native.c4queryobs_create(_query, QueryCallback, GCHandle.ToIntPtr(handle).ToPointer());
                    //CHECK(_queryObserver2);
                    Native.c4queryobs_setEnabled(_queryObserver2, true);

                    WriteLine("---- Waiting for query observers...");
                    Thread.Sleep(2000);

                    WriteLine("Checking query observers...");
                    _queryCallbackCalls.Should().Be(1, "because we should have received a callback");
                    var e1 = (C4QueryEnumerator *)LiteCoreBridge.Check(err =>
                    {
                        return(Native.c4queryobs_getEnumerator(_queryObserver, true, err));
                    });
                    //REQUIRE(e1);
                    //CHECK(error.code == 0);
                    Native.c4queryenum_getRowCount(e1, &error).Should().Be(8);
                    _queryCallbackCalls2.Should().Be(1, "because we should have received a callback");
                    var e2 = (C4QueryEnumerator *)LiteCoreBridge.Check(err =>
                    {
                        return(Native.c4queryobs_getEnumerator(_queryObserver2, true, err));
                    });
                    //REQUIRE(e2);
                    //CHECK(error.code == 0);
                    //CHECK(e2 != e1);
                    Native.c4queryenum_getRowCount(e2, &error).Should().Be(8);

                    _queryObserver3 = Native.c4queryobs_create(_query, QueryCallback, GCHandle.ToIntPtr(handle).ToPointer());
                    //CHECK(_queryObserver3);
                    Native.c4queryobs_setEnabled(_queryObserver3, true);

                    WriteLine("---- Waiting for a new query observer...");
                    Thread.Sleep(2000);

                    WriteLine("Checking a new query observer...");
                    _queryCallbackCalls3.Should().Be(1, "because we should have received a callback");
                    var e3 = (C4QueryEnumerator *)LiteCoreBridge.Check(err =>
                    {
                        return(Native.c4queryobs_getEnumerator(_queryObserver3, true, err));
                    });
                    //REQUIRE(e3);
                    //CHECK(error.code == 0);
                    //CHECK(e3 != e2);
                    Native.c4queryenum_getRowCount(e3, &error).Should().Be(8);

                    WriteLine("Iterating all query results...");
                    int count = 0;
                    while (Native.c4queryenum_next(e1, null) && Native.c4queryenum_next(e2, null) && Native.c4queryenum_next(e3, null))
                    {
                        ++count;
                        FLArrayIterator col1 = e1->columns;
                        FLArrayIterator col2 = e2->columns;
                        FLArrayIterator col3 = e3->columns;
                        var c = Native.FLArrayIterator_GetCount(&col1);
                        c.Should().Be(Native.FLArrayIterator_GetCount(&col2));
                        c.Should().Be(Native.FLArrayIterator_GetCount(&col3));
                        for (uint i = 0; i < c; ++i)
                        {
                            var v1 = Native.FLArrayIterator_GetValueAt(&col1, i);
                            var v2 = Native.FLArrayIterator_GetValueAt(&col2, i);
                            var v3 = Native.FLArrayIterator_GetValueAt(&col3, i);
                            Native.FLValue_IsEqual(v1, v2).Should().BeTrue();
                            Native.FLValue_IsEqual(v2, v3).Should().BeTrue();
                        }
                    }

                    count.Should().Be(8);
                } finally {
                    handle.Free();
                }
            });
        }
Exemplo n.º 6
0
        public void TestQueryObserver()
        {
            RunTestVariants(() =>
            {
                var handle = GCHandle.Alloc(this);
                try {
                    Compile(Json5("['=', ['.', 'contact', 'address', 'state'], 'CA']"));
                    C4Error error;

                    /** Creates a new query observer, with a callback that will be invoked when the query
                     *  results change, with an enumerator containing the new results.
                     *  \note The callback isn't invoked immediately after a change, and won't be invoked after
                     *  every change, to avoid performance problems. Instead, there's a brief delay so multiple
                     *  changes can be coalesced.
                     *  \note The new observer needs to be enabled by calling \ref c4queryobs_setEnabled.
                     */
                    _queryObserver = Native.c4queryobs_create(_query, QueryCallback, GCHandle.ToIntPtr(handle).ToPointer());
                    /** Enables a query observer so its callback can be called, or disables it to stop callbacks. */
                    Native.c4queryobs_setEnabled(_queryObserver, true);

                    WriteLine("---- Waiting for query observer...");
                    Thread.Sleep(2000);

                    WriteLine("Checking query observer...");
                    _queryCallbackCalls.Should().Be(1, "because we should have received a callback");
                    var e = (C4QueryEnumerator *)LiteCoreBridge.Check(err =>
                    {
                        /** Returns the current query results, if any.
                         * When the observer is created, the results are initially NULL until the query finishes
                         * running in the background.
                         * Once the observer callback is called, the results are available.
                         * \note  You are responsible for releasing the returned reference.
                         * @param obs  The query observer.
                         * @param forget  If true, the observer will not hold onto the enumerator, and subsequent calls
                         * will return NULL until the next time the observer notifies you. This can help
                         * conserve memory, since the query result data will be freed as soon as you
                         * release the enumerator.
                         * @param error  If the last evaluation of the query failed, the error will be stored here.
                         * @return  The current query results, or NULL if the query hasn't run or has failed.
                         */
                        return(Native.c4queryobs_getEnumerator(_queryObserver, true, err));
                    });
                    //REQUIRE(e);
                    //CHECK(c4queryobs_getEnumerator(state.obs, true, &error) == nullptr);
                    //CHECK(error.code == 0);
                    Native.c4queryenum_getRowCount(e, &error).Should().Be(8);

                    AddPersonInState("after1", "AL");

                    WriteLine("---- Checking that query observer doesn't fire...");
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                    _queryCallbackCalls.Should().Be(1);

                    WriteLine("---- Changing a doc in the query");
                    LiteCoreBridge.Check(err => Native.c4db_beginTransaction(Db, err));
                    try {
                        AddPersonInState("after2", "CA");
                        // wait, to make sure the observer doesn't try to run the query before the commit
                        Thread.Sleep(TimeSpan.FromSeconds(1));
                        WriteLine("---- Commiting changes");
                    } finally {
                        LiteCoreBridge.Check(err => Native.c4db_endTransaction(Db, true, err));
                    }

                    WriteLine("---- Waiting for 2nd call of query observer...");
                    Thread.Sleep(2000);

                    WriteLine("---- Checking query observer again...");
                    _queryCallbackCalls.Should().Be(2, "because we should have received a callback");
                    var e2 = (C4QueryEnumerator *)LiteCoreBridge.Check(err =>
                    {
                        return(Native.c4queryobs_getEnumerator(_queryObserver, false, err));
                    });
                    //REQUIRE(e2);
                    //CHECK(e2 != e);
                    var e3 = (C4QueryEnumerator *)LiteCoreBridge.Check(err =>
                    {
                        return(Native.c4queryobs_getEnumerator(_queryObserver, false, err));
                    });
                    //CHECK(e3 == e2);
                    Native.c4queryenum_getRowCount(e2, &error).Should().Be(9);

                    // Testing with purged document:
                    WriteLine("---- Purging a document...");
                    LiteCoreBridge.Check(err => Native.c4db_beginTransaction(Db, err));
                    try {
                        Native.c4db_purgeDoc(Db, "after2", &error);
                        WriteLine("---- Commiting changes");
                    } finally {
                        LiteCoreBridge.Check(err => Native.c4db_endTransaction(Db, true, err));
                    }

                    WriteLine("---- Waiting for 3rd call of query observer...");
                    Thread.Sleep(2000);

                    WriteLine("---- Checking query observer again...");
                    _queryCallbackCalls.Should().Be(3, "because we should have received a callback");
                    e2 = (C4QueryEnumerator *)LiteCoreBridge.Check(err =>
                    {
                        return(Native.c4queryobs_getEnumerator(_queryObserver, true, err));
                    });
                    //REQUIRE(e2);
                    //CHECK(e2 != e);
                    Native.c4queryenum_getRowCount(e2, &error).Should().Be(8);
                } finally {
                    handle.Free();
                }
            });
        }
Exemplo n.º 7
0
 public static extern C4QueryEnumerator *c4queryobs_getEnumerator(C4QueryObserver *obs, [MarshalAs(UnmanagedType.U1)] bool forget, C4Error *error);
Exemplo n.º 8
0
 public static extern void c4queryobs_setEnabled(C4QueryObserver *obs, [MarshalAs(UnmanagedType.U1)] bool enabled);
Exemplo n.º 9
0
 public static extern void c4queryobs_free(C4QueryObserver *x);