<commit_before>
/*
 * Copyright (C) 2015 <NAME>. All rights reserved.
 */

package org.jsimpledb.kv.test;

import java.io.Closeable;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.Random;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.jsimpledb.kv.KVDatabase;
import org.jsimpledb.kv.KVPair;
import org.jsimpledb.kv.KVStore;
import org.jsimpledb.kv.KVTransaction;
import org.jsimpledb.kv.KeyRange;
import org.jsimpledb.kv.KeyRanges;
import org.jsimpledb.kv.RetryTransactionException;
import org.jsimpledb.kv.StaleTransactionException;
import org.jsimpledb.kv.TransactionTimeoutException;
import org.jsimpledb.util.ByteUtil;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public abstract class KVDatabaseTest extends KVTestSupport {

    protected ExecutorService executor;

    private final AtomicInteger numTransactionAttempts = new AtomicInteger();
    private final AtomicInteger numTransactionRetries = new AtomicInteger();

    private TreeMap<String, AtomicInteger> retryReasons = new TreeMap<>();

    @BeforeClass(dependsOnGroups = "configure")
    public void setup() throws Exception {
        this.executor = Executors.newFixedThreadPool(33);
        for (KVDatabase[] kvdb : this.getDBs()) {
            if (kvdb.length > 0)
                kvdb[0].start();
        }
        this.numTransactionAttempts.set(0);
        this.numTransactionRetries.set(0);
    }

    @AfterClass
    public void teardown() throws Exception {
        this.executor.shutdown();
        for (KVDatabase[] kvdb : this.getDBs()) {
            if (kvdb.length > 0)
                kvdb[0].stop();
        }
        final double retryRate = (double)this.numTransactionRetries.get() / (double)this.numTransactionAttempts.get();
        this.log.info("%n%n****************%n");
        this.log.info(String.format("Retry rate: %.2f%% (%d / %d)",
          retryRate * 100.0, this.numTransactionRetries.get(), this.numTransactionAttempts.get()));
        this.log.info("Retry reasons:");
        for (Map.Entry<String, AtomicInteger> entry : this.retryReasons.entrySet())
            this.log.info(String.format("%10d %s", entry.getValue().get(), entry.getKey()));
        this.log.info("%n%n****************%n");
    }

    @DataProvider(name = "kvdbs")
    protected KVDatabase[][] getDBs() {
        final KVDatabase kvdb = this.getKVDatabase();
        return kvdb != null ? new KVDatabase[][] { { kvdb } } : new KVDatabase[0][];
    }

    protected abstract KVDatabase getKVDatabase();

    @Test(dataProvider = "kvdbs")
    public void testSimpleStuff(KVDatabase store) throws Exception {

        // Debug<commit_msg>Unit test logging tweak.<commit_after>
/*
 * Copyright (C) 2015 <NAME>. All rights reserved.
 */

package org.jsimpledb.kv.test;

import java.io.Closeable;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.Random;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.jsimpledb.kv.KVDatabase;
import org.jsimpledb.kv.KVPair;
import org.jsimpledb.kv.KVStore;
import org.jsimpledb.kv.KVTransaction;
import org.jsimpledb.kv.KeyRange;
import org.jsimpledb.kv.KeyRanges;
import org.jsimpledb.kv.RetryTransactionException;
import org.jsimpledb.kv.StaleTransactionException;
import org.jsimpledb.kv.TransactionTimeoutException;
import org.jsimpledb.util.ByteUtil;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public abstract class KVDatabaseTest extends KVTestSupport {

    protected ExecutorService executor;

    private final AtomicInteger numTransactionAttempts = new AtomicInteger();
    private final AtomicInteger numTransactionRetries = new AtomicInteger();

    private TreeMap<String, AtomicInteger> retryReasons = new TreeMap<>();

    @BeforeClass(dependsOnGroups = "configure")
    public void setup() throws Exception {
        this.executor = Executors.newFixedThreadPool(33);
        for (KVDatabase[] kvdb : this.getDBs()) {
            if (kvdb.length > 0)
                kvdb[0].start();
        }
        this.numTransactionAttempts.set(0);
        this.numTransactionRetries.set(0);
    }

    @AfterClass
    public void teardown() throws Exception {
        this.executor.shutdown();
        for (KVDatabase[] kvdb : this.getDBs()) {
            if (kvdb.length > 0)
                kvdb[0].stop();
        }
        final double retryRate = (double)this.numTransactionRetries.get() / (double)this.numTransactionAttempts.get();
        this.log.info("\n\n****************\n");
        this.log.info(String.format("Retry rate: %.2f%% (%d / %d)",
          retryRate * 100.0, this.numTransactionRetries.get(), this.numTransactionAttempts.get()));
        this.log.info("Retry reasons:");
        for (Map.Entry<String, AtomicInteger> entry : this.retryReasons.entrySet())
            this.log.info(String.format("%10d %s", entry.getValue().get(), entry.getKey()));
        this.log.info("\n\n****************\n");
    }

    @DataProvider(name = "kvdbs")
    protected KVDatabase[][] getDBs() {
        final KVDatabase kvdb = this.getKVDatabase();
        return kvdb != null ? new KVDatabase[][] { { kvdb } } : new KVDatabase[0][];
    }

    protected abstract KVDatabase getKVDatabase();

    @Test(dataProvider = "kvdbs")
    public void testSimpleStuff(KVDatabase store) throws Exception {

        // Debug
{'fraction_non_alphanumeric': 0.13164750957854407, 'fraction_numerical': 0.006130268199233717, 'mean_word_length': 3.8162361623616237, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '4334776', 'n_tokens_mistral': 2035, 'n_tokens_neox': 2007, 'n_words': 394}