@@ -454,4 +454,101 @@ public void testForceInsertWithNonStringForTypeField() throws CouchbaseLiteExcep
454454 history = Arrays .asList (rev .getRevID ());
455455 database .forceInsert (rev , history , null );
456456 }
457+
458+ /**
459+ * Missing changes in Database Change Notification
460+ * https://github.com/couchbase/couchbase-lite-java-core/issues/1147
461+ */
462+ public void testDatabaseChangeNotification () throws Exception {
463+ if (!this .isSQLiteDB ())
464+ return ;
465+
466+ final int numDocs = 1000 ;
467+ final int batchSize = 20 ;
468+ final AtomicInteger totalChangesCount = new AtomicInteger (0 );
469+ final CountDownLatch changesCountDownLatch = new CountDownLatch (1 );
470+ final CountDownLatch createDocsCountDownLatch = new CountDownLatch (2 );
471+
472+ database .addChangeListener (new Database .ChangeListener () {
473+ @ Override
474+ public void changed (Database .ChangeEvent event ) {
475+ synchronized (totalChangesCount ) {
476+ int total = totalChangesCount .addAndGet (event .getChanges ().size ());
477+ Log .e (TAG , "Total changes : " + total + " > " + Thread .currentThread ().getName ());
478+ if (total == numDocs * 2 ) {
479+ changesCountDownLatch .countDown ();
480+ }
481+ }
482+ }
483+ });
484+
485+ final Thread t1 = new Thread (new Runnable () {
486+ @ Override
487+ public void run () {
488+ int numRounds = numDocs / batchSize ;
489+ for (int i = 0 ; i < numRounds ; i ++) {
490+ database .runInTransaction (new TransactionalTask () {
491+ @ Override
492+ public boolean run () {
493+ for (int j = 0 ; j < batchSize ; j ++) {
494+ Document doc = database .createDocument ();
495+ Map <String , Object > props = new HashMap <String , Object >();
496+ props .put ("foo" , "bar" );
497+ try {
498+ doc .putProperties (props );
499+ } catch (CouchbaseLiteException e ) {
500+ Log .e (TAG , "Error creating a document" , e );
501+ return false ;
502+ }
503+ }
504+ return true ;
505+ }
506+ });
507+ }
508+ synchronized (createDocsCountDownLatch ) {
509+ createDocsCountDownLatch .countDown ();
510+ }
511+ }
512+ }, "T1" );
513+ t1 .start ();
514+
515+ final Thread t2 = new Thread (new Runnable () {
516+ @ Override
517+ public void run () {
518+ int numRounds = numDocs / batchSize ;
519+ for (int i = 0 ; i < numRounds ; i ++) {
520+ database .runInTransaction (new TransactionalTask () {
521+ @ Override
522+ public boolean run () {
523+ for (int j = 0 ; j < batchSize ; j ++) {
524+ Document doc = database .createDocument ();
525+ Map <String , Object > props = new HashMap <String , Object >();
526+ props .put ("foo" , "bar" );
527+ try {
528+ doc .putProperties (props );
529+ } catch (CouchbaseLiteException e ) {
530+ Log .e (TAG , "Error creating a document" , e );
531+ return false ;
532+ }
533+ }
534+ return true ;
535+ }
536+ });
537+ }
538+ synchronized (createDocsCountDownLatch ) {
539+ createDocsCountDownLatch .countDown ();
540+ }
541+ }
542+ }, "T2" );
543+ t2 .start ();
544+
545+ createDocsCountDownLatch .await ();
546+ Log .e (TAG , "Both T1 and T2 are done creating docs : " + database .getDocumentCount ());
547+
548+ assertTrue (changesCountDownLatch .await (60 , TimeUnit .SECONDS ));
549+ assertEquals (numDocs * 2 , totalChangesCount .get ());
550+
551+ // If not sleeping, sometimes not get all logging messages after the unit test got tear down.
552+ Thread .sleep (5000 );
553+ }
457554}
0 commit comments