/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2002, 2015 Oracle and/or its affiliates. All rights reserved.
*
*/
package com.sleepycat.util.test;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import com.sleepycat.compat.DbCompat;
import com.sleepycat.db.CursorConfig;
import com.sleepycat.db.DatabaseException;
import com.sleepycat.db.Environment;
import com.sleepycat.db.EnvironmentConfig;
import com.sleepycat.db.Transaction;
import com.sleepycat.db.TransactionConfig;
import com.sleepycat.db.util.DualTestCase;
/**
* Permutes test cases over three transaction types: null (non-transactional),
* auto-commit, and user (explicit).
*
* <p>Overrides runTest, setUp and tearDown to open/close the environment and
* to set up protected members for use by test cases.</p>
*
* <p>If a subclass needs to override setUp or tearDown, the overridden method
* should call super.setUp or super.tearDown.</p>
*
* <p>When writing a test case based on this class, write it as if a user txn
* were always used: call txnBegin, txnCommit and txnAbort for all write
* operations. Use the isTransactional protected field for setup of a database
* config.</p>
*/
public abstract class TxnTestCase extends DualTestCase {
public static final String TXN_NULL = "txn-null";
public static final String TXN_AUTO = "txn-auto";
public static final String TXN_USER = "txn-user";
public static final String TXN_CDB = "txn-cdb";
protected File envHome;
protected Environment env;
protected EnvironmentConfig envConfig;
protected String txnType;
protected boolean isTransactional;
public static List<Object[]> getTxnParams(String[] txnTypes, boolean rep) {
final List<Object[]> list = new ArrayList<Object[]>();
for (final String type : getTxnTypes(txnTypes, rep)) {
list.add(new Object[] {type});
}
return list;
}
public static String[] getTxnTypes(String[] txnTypes, boolean rep) {
if (txnTypes == null) {
if (rep) {
txnTypes = new String[] { // Skip non-transactional tests
TxnTestCase.TXN_USER,
TxnTestCase.TXN_AUTO };
} else if (!DbCompat.CDB) {
txnTypes = new String[] { TxnTestCase.TXN_NULL,
TxnTestCase.TXN_USER,
TxnTestCase.TXN_AUTO };
} else {
txnTypes = new String[] { TxnTestCase.TXN_NULL,
TxnTestCase.TXN_USER,
TxnTestCase.TXN_AUTO,
TxnTestCase.TXN_CDB };
}
} else {
if (!DbCompat.CDB) {
/* Remove TxnTestCase.TXN_CDB, if there is any. */
final ArrayList<String> tmp =
new ArrayList<String>(Arrays.asList(txnTypes));
tmp.remove(TxnTestCase.TXN_CDB);
txnTypes = new String[tmp.size()];
tmp.toArray(txnTypes);
}
}
return txnTypes;
}
@Before
public void setUp()
throws Exception {
super.setUp();
envHome = SharedTestUtils.getNewDir();
openEnv();
}
@After
public void tearDown()
throws Exception {
super.tearDown();
closeEnv();
env = null;
}
protected void initEnvConfig() {
if (envConfig == null) {
envConfig = new EnvironmentConfig();
envConfig.setAllowCreate(true);
/* Always use write-no-sync (by default) to speed up tests. */
if (!envConfig.getTxnNoSync() && !envConfig.getTxnWriteNoSync()) {
envConfig.setTxnWriteNoSync(true);
}
}
}
/**
* Closes the environment and sets the env field to null.
* Used for closing and reopening the environment.
*/
public void closeEnv()
throws DatabaseException {
if (env != null) {
close(env);
env = null;
}
}
/**
* Opens the environment based on the txnType for this test case.
* Used for closing and reopening the environment.
*/
public void openEnv()
throws DatabaseException {
if (txnType == TXN_NULL) {
TestEnv.BDB.copyConfig(envConfig);
env = create(envHome, envConfig);
} else if (txnType == TXN_AUTO) {
TestEnv.TXN.copyConfig(envConfig);
env = create(envHome, envConfig);
} else if (txnType == TXN_USER) {
TestEnv.TXN.copyConfig(envConfig);
env = create(envHome, envConfig);
} else if (txnType == TXN_CDB) {
TestEnv.CDB.copyConfig(envConfig);
env = create(envHome, envConfig);
} else {
assert false;
}
}
/**
* Begin a txn if in TXN_USER mode; otherwise return null;
*/
protected Transaction txnBegin()
throws DatabaseException {
return txnBegin(null, null);
}
/**
* Begin a txn if in TXN_USER mode; otherwise return null;
*/
protected Transaction txnBegin(Transaction parentTxn,
TransactionConfig config)
throws DatabaseException {
if (txnType == TXN_USER) {
return env.beginTransaction(parentTxn, config);
}
return null;
}
/**
* Begin a txn if in TXN_USER or TXN_AUTO mode; otherwise return null;
*/
protected Transaction txnBeginCursor()
throws DatabaseException {
return txnBeginCursor(null, null);
}
/**
* Begin a txn if in TXN_USER or TXN_AUTO mode; otherwise return null;
*/
protected Transaction txnBeginCursor(Transaction parentTxn,
TransactionConfig config)
throws DatabaseException {
if (txnType == TXN_USER || txnType == TXN_AUTO) {
return env.beginTransaction(parentTxn, config);
} else {
return null;
}
}
/**
* Create a write cursor config;
*/
public CursorConfig getWriteCursorConfig() {
if (txnType != TXN_CDB) {
return null;
}
final CursorConfig config = new CursorConfig();
DbCompat.setWriteCursor(config, true);
return config;
}
/**
* Commit a txn if non-null.
*/
protected void txnCommit(Transaction txn)
throws DatabaseException {
if (txn != null) {
txn.commit();
}
}
/**
* Commit a txn if non-null.
*/
protected void txnAbort(Transaction txn)
throws DatabaseException {
if (txn != null) {
txn.abort();
}
}
}