<commit_before>//
// Copyright (c) 2016 Couchbase, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
package com.couchbase.lite.multithreads;

import com.couchbase.lite.CouchbaseLiteException;
import com.couchbase.lite.Database;
import com.couchbase.lite.Document;
import com.couchbase.lite.Emitter;
import com.couchbase.lite.LiteTestCaseWithDB;
import com.couchbase.lite.Mapper;
import com.couchbase.lite.Query;
import com.couchbase.lite.QueryEnumerator;
import com.couchbase.lite.QueryRow;
import com.couchbase.lite.View;
import com.couchbase.lite.internal.RevisionInternal;
import com.couchbase.lite.util.Log;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by hideki on 6/29/16.
 */
public class MultiThreadsTest extends LiteTestCaseWithDB {
    private static final String TAG = MultiThreadsTest.class.getName();

    @Override
    protected void setUp() throws Exception {
        if (!multithreadsTestsEnabled()) {
            return;
        }

        super.setUp();
    }

    public void testInsertAndQueryThreads() {

        if (!multithreadsTestsEnabled())
            return;

        // create view
        final View view = createView(database);

        final AtomicInteger count = new AtomicInteger();
        Thread insertThread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 500; i++) {
                    String docID = String.format(Locale.ENGLISH, "docID-%08d", count.incrementAndGet());
                    Document doc = database.getDocument(docID);
                    Map<String, Object> props = new HashMap<String, Object>();
                    props.put("key", count.get());
                    try {
                        doc.putProperties(props);
                    } catch (CouchbaseLiteException e) {
                        Log.e(TAG, "Error in Document.putProperty(). ", e);
                        fail(e.getMessage());
                    }
                }
            }
        });

        Thread queryThread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    Query query = view.createQuery();
                    try {
                        for (QueryRow row : query.run()) {
                            Log.i(TAG, "row=%s", row.getDocumentId());
                        }
                    } catch (CouchbaseLiteException e) {
                        Log.e(TAG, "Error in Query.run(). ", e);
                        fail(e.getMessage());
                    }
                }
            }
        });

        queryThread.start();
        insertThread.start();

        try {
            insertThread.join();
        } catch (InterruptedException e) {
            Log.e(TAG, "Error in insertThread. ", e);
        }
        try {
            queryThread.join();
        } catch (InterruptedException e) {
            Log.e(TAG, "Error in insertThread. ", e);
        }
    }

    public static View createView(Database db) {
        return createView(db, "aview");
    }

    public static View createView(Database db, String name) {
        View view = db.getView(name);
        if (view != null) {
            view.setMapReduce(new Mapper() {
                @Override
                public void map(Map<String, Object> document, Emitter emitter) {
                    if (document.get("key") != null)
                        emitter.emit(document.get("key"), null);
                }
            }, null, "1");
        }
        return view;
    }

    public void testUpdateDocsAndReadRevHistory() throws Exception {
        if (!multithreadsTestsEnabled())
            return;
        // ForestDB can not pass this test.
        // https://github.com/couchbase/couchbase-lite-java-core/issues/1437
        if (!isSQLiteDB())
            return;

        // Insert docs
        Thread insertThread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    String docID = String.format(Locale.ENGLISH, "docID-%08d", i);
                    Document doc = database.getDocument(docID);
                    Map<String, Object> props = new HashMap<String, Object>();
                    props.put("key", i);
                    try {
                        doc.putProperties(props);<commit_msg>Fixed #1437 - Enabled testUpdateDocsAndReadRevHistory() test for forestdb and added comment for testing.<commit_after>//
// Copyright (c) 2016 Couchbase, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
package com.couchbase.lite.multithreads;

import com.couchbase.lite.CouchbaseLiteException;
import com.couchbase.lite.Database;
import com.couchbase.lite.Document;
import com.couchbase.lite.Emitter;
import com.couchbase.lite.LiteTestCaseWithDB;
import com.couchbase.lite.Mapper;
import com.couchbase.lite.Query;
import com.couchbase.lite.QueryEnumerator;
import com.couchbase.lite.QueryRow;
import com.couchbase.lite.View;
import com.couchbase.lite.internal.RevisionInternal;
import com.couchbase.lite.util.Log;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by hideki on 6/29/16.
 */
public class MultiThreadsTest extends LiteTestCaseWithDB {
    private static final String TAG = MultiThreadsTest.class.getName();

    @Override
    protected void setUp() throws Exception {
        if (!multithreadsTestsEnabled()) {
            return;
        }

        super.setUp();
    }

    public void testInsertAndQueryThreads() {

        if (!multithreadsTestsEnabled())
            return;

        // create view
        final View view = createView(database);

        final AtomicInteger count = new AtomicInteger();
        Thread insertThread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 500; i++) {
                    String docID = String.format(Locale.ENGLISH, "docID-%08d", count.incrementAndGet());
                    Document doc = database.getDocument(docID);
                    Map<String, Object> props = new HashMap<String, Object>();
                    props.put("key", count.get());
                    try {
                        doc.putProperties(props);
                    } catch (CouchbaseLiteException e) {
                        Log.e(TAG, "Error in Document.putProperty(). ", e);
                        fail(e.getMessage());
                    }
                }
            }
        });

        Thread queryThread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    Query query = view.createQuery();
                    try {
                        for (QueryRow row : query.run()) {
                            Log.i(TAG, "row=%s", row.getDocumentId());
                        }
                    } catch (CouchbaseLiteException e) {
                        Log.e(TAG, "Error in Query.run(). ", e);
                        fail(e.getMessage());
                    }
                }
            }
        });

        queryThread.start();
        insertThread.start();

        try {
            insertThread.join();
        } catch (InterruptedException e) {
            Log.e(TAG, "Error in insertThread. ", e);
        }
        try {
            queryThread.join();
        } catch (InterruptedException e) {
            Log.e(TAG, "Error in insertThread. ", e);
        }
    }

    public static View createView(Database db) {
        return createView(db, "aview");
    }

    public static View createView(Database db, String name) {
        View view = db.getView(name);
        if (view != null) {
            view.setMapReduce(new Mapper() {
                @Override
                public void map(Map<String, Object> document, Emitter emitter) {
                    if (document.get("key") != null)
                        emitter.emit(document.get("key"), null);
                }
            }, null, "1");
        }
        return view;
    }

    /**
     * IMPORTANT: DON'T run this test with Genymotion emulator with Android 4.x or older. It caseus
     * unknown crash.
     * https://github.com/couchbase/couchbase-lite-java-core/issues/1437
     */
    public void testUpdateDocsAndReadRevHistory() throws Exception {
        if (!multithreadsTestsEnabled())
            return;

        // Insert docs
        Thread insertThread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    String docID = String.format(Locale.ENGLISH, "docID-%08d", i);
                    Document doc = database.getDocument(docID);
                    Map<String, Object> props = new HashMap<String, Object>();
                    props.put("key", i);
                    try {
                        doc.putProperties(props);
{'fraction_non_alphanumeric': 0.10773855702094647, 'fraction_numerical': 0.0070791311093871215, 'mean_word_length': 1.7752960172228203, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 13, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6274437', 'n_tokens_mistral': 2851, 'n_tokens_neox': 2668, 'n_words': 744}