1 /*- 2 * Copyright (c) 2002, 2020 Oracle and/or its affiliates. All rights reserved. 3 * 4 * See the file LICENSE for license information. 5 * 6 */ 7 8 package com.sleepycat.util.test; 9 10 import java.io.File; 11 import java.util.ArrayList; 12 import java.util.Arrays; 13 import java.util.List; 14 15 import org.junit.After; 16 import org.junit.Before; 17 18 import com.sleepycat.compat.DbCompat; 19 import com.sleepycat.db.CursorConfig; 20 import com.sleepycat.db.DatabaseException; 21 import com.sleepycat.db.Environment; 22 import com.sleepycat.db.EnvironmentConfig; 23 import com.sleepycat.db.Transaction; 24 import com.sleepycat.db.TransactionConfig; 25 import com.sleepycat.db.util.DualTestCase; 26 27 /** 28 * Permutes test cases over three transaction types: null (non-transactional), 29 * auto-commit, and user (explicit). 30 * 31 * <p>Overrides runTest, setUp and tearDown to open/close the environment and 32 * to set up protected members for use by test cases.</p> 33 * 34 * <p>If a subclass needs to override setUp or tearDown, the overridden method 35 * should call super.setUp or super.tearDown.</p> 36 * 37 * <p>When writing a test case based on this class, write it as if a user txn 38 * were always used: call txnBegin, txnCommit and txnAbort for all write 39 * operations. Use the isTransactional protected field for setup of a database 40 * config.</p> 41 */ 42 public abstract class TxnTestCase extends DualTestCase { 43 44 public static final String TXN_NULL = "txn-null"; 45 public static final String TXN_AUTO = "txn-auto"; 46 public static final String TXN_USER = "txn-user"; 47 public static final String TXN_CDB = "txn-cdb"; 48 49 protected File envHome; 50 protected Environment env; 51 protected EnvironmentConfig envConfig; 52 protected String txnType; 53 protected boolean isTransactional; 54 getTxnParams(String[] txnTypes, boolean rep)55 public static List<Object[]> getTxnParams(String[] txnTypes, boolean rep) { 56 final List<Object[]> list = new ArrayList<>(); 57 for (final String type : getTxnTypes(txnTypes, rep)) { 58 list.add(new Object[] {type}); 59 } 60 return list; 61 } 62 getTxnTypes(String[] txnTypes, boolean rep)63 public static String[] getTxnTypes(String[] txnTypes, boolean rep) { 64 if (txnTypes == null) { 65 if (rep) { 66 txnTypes = new String[] { // Skip non-transactional tests 67 TxnTestCase.TXN_USER, 68 TxnTestCase.TXN_AUTO }; 69 } else if (!DbCompat.CDB) { 70 txnTypes = new String[] { TxnTestCase.TXN_NULL, 71 TxnTestCase.TXN_USER, 72 TxnTestCase.TXN_AUTO }; 73 } else { 74 txnTypes = new String[] { TxnTestCase.TXN_NULL, 75 TxnTestCase.TXN_USER, 76 TxnTestCase.TXN_AUTO, 77 TxnTestCase.TXN_CDB }; 78 } 79 } else { 80 if (!DbCompat.CDB) { 81 /* Remove TxnTestCase.TXN_CDB, if there is any. */ 82 final ArrayList<String> tmp = 83 new ArrayList<>(Arrays.asList(txnTypes)); 84 tmp.remove(TxnTestCase.TXN_CDB); 85 txnTypes = new String[tmp.size()]; 86 tmp.toArray(txnTypes); 87 } 88 } 89 return txnTypes; 90 } 91 92 @Before setUp()93 public void setUp() 94 throws Exception { 95 96 super.setUp(); 97 envHome = SharedTestUtils.getNewDir(); 98 openEnv(); 99 } 100 101 @After tearDown()102 public void tearDown() 103 throws Exception { 104 105 super.tearDown(); 106 closeEnv(); 107 env = null; 108 } 109 initEnvConfig()110 protected void initEnvConfig() { 111 if (envConfig == null) { 112 envConfig = new EnvironmentConfig(); 113 envConfig.setAllowCreate(true); 114 115 /* Always use write-no-sync (by default) to speed up tests. */ 116 if (!envConfig.getTxnNoSync() && !envConfig.getTxnWriteNoSync()) { 117 envConfig.setTxnWriteNoSync(true); 118 } 119 } 120 } 121 122 /** 123 * Closes the environment and sets the env field to null. 124 * Used for closing and reopening the environment. 125 */ closeEnv()126 public void closeEnv() 127 throws DatabaseException { 128 129 if (env != null) { 130 close(env); 131 env = null; 132 } 133 } 134 135 /** 136 * Opens the environment based on the txnType for this test case. 137 * Used for closing and reopening the environment. 138 */ openEnv()139 public void openEnv() 140 throws DatabaseException { 141 142 if (txnType == TXN_NULL) { 143 TestEnv.BDB.copyConfig(envConfig); 144 env = create(envHome, envConfig); 145 } else if (txnType == TXN_AUTO) { 146 TestEnv.TXN.copyConfig(envConfig); 147 env = create(envHome, envConfig); 148 } else if (txnType == TXN_USER) { 149 TestEnv.TXN.copyConfig(envConfig); 150 env = create(envHome, envConfig); 151 } else if (txnType == TXN_CDB) { 152 TestEnv.CDB.copyConfig(envConfig); 153 env = create(envHome, envConfig); 154 } else { 155 assert false; 156 } 157 } 158 159 /** 160 * Begin a txn if in TXN_USER mode; otherwise return null; 161 */ txnBegin()162 protected Transaction txnBegin() 163 throws DatabaseException { 164 165 return txnBegin(null, null); 166 } 167 168 /** 169 * Begin a txn if in TXN_USER mode; otherwise return null; 170 */ txnBegin(Transaction parentTxn, TransactionConfig config)171 protected Transaction txnBegin(Transaction parentTxn, 172 TransactionConfig config) 173 throws DatabaseException { 174 175 if (txnType == TXN_USER) { 176 return env.beginTransaction(parentTxn, config); 177 } 178 return null; 179 } 180 181 /** 182 * Begin a txn if in TXN_USER or TXN_AUTO mode; otherwise return null; 183 */ txnBeginCursor()184 protected Transaction txnBeginCursor() 185 throws DatabaseException { 186 187 return txnBeginCursor(null, null); 188 } 189 190 /** 191 * Begin a txn if in TXN_USER or TXN_AUTO mode; otherwise return null; 192 */ txnBeginCursor(Transaction parentTxn, TransactionConfig config)193 protected Transaction txnBeginCursor(Transaction parentTxn, 194 TransactionConfig config) 195 throws DatabaseException { 196 197 if (txnType == TXN_USER || txnType == TXN_AUTO) { 198 return env.beginTransaction(parentTxn, config); 199 } else { 200 return null; 201 } 202 } 203 204 /** 205 * Create a write cursor config; 206 */ getWriteCursorConfig()207 public CursorConfig getWriteCursorConfig() { 208 if (txnType != TXN_CDB) { 209 return null; 210 } 211 final CursorConfig config = new CursorConfig(); 212 DbCompat.setWriteCursor(config, true); 213 return config; 214 } 215 216 /** 217 * Commit a txn if non-null. 218 */ txnCommit(Transaction txn)219 protected void txnCommit(Transaction txn) 220 throws DatabaseException { 221 222 if (txn != null) { 223 txn.commit(); 224 } 225 } 226 227 /** 228 * Commit a txn if non-null. 229 */ txnAbort(Transaction txn)230 protected void txnAbort(Transaction txn) 231 throws DatabaseException { 232 233 if (txn != null) { 234 txn.abort(); 235 } 236 } 237 } 238