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