2 Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 package testsuite.clusterj;
20 import com.mysql.clusterj.ClusterJException;
21 import com.mysql.clusterj.ClusterJHelper;
23 import com.mysql.clusterj.Constants;
24 import com.mysql.clusterj.Session;
25 import com.mysql.clusterj.SessionFactory;
26 import com.mysql.clusterj.Transaction;
28 import java.io.BufferedReader;
30 import java.io.FileInputStream;
31 import java.io.FileNotFoundException;
32 import java.io.IOException;
33 import java.io.InputStream;
35 import java.io.InputStreamReader;
36 import java.sql.Connection;
37 import java.sql.DriverManager;
38 import java.sql.PreparedStatement;
39 import java.sql.SQLException;
40 import java.util.ArrayList;
41 import java.util.Collection;
42 import java.util.Collections;
43 import java.util.Comparator;
44 import java.util.Iterator;
45 import java.util.LinkedList;
46 import java.util.List;
47 import java.util.Map.Entry;
48 import java.util.Properties;
50 import junit.framework.TestCase;
52 public abstract class AbstractClusterJCoreTest extends TestCase {
55 * Indicates an exception thrown in method <code>tearDown</code>.
56 * At the end of method <code>tearDown</code> this field is nullified.
58 private Throwable tearDownThrowable;
61 * A list of registered oid instances.
62 * Corresponding pc instances are deleted in <code>localTearDown</code>.
64 private Collection tearDownInstances = new LinkedList();
67 * A list of registered pc classes.
68 * The extents of these classes are deleted in <code>tearDown</code>.
70 private Collection<Class> tearDownClasses = new LinkedList<Class>();
73 * Error messages collected during a test.
75 private StringBuffer errorMessages;
77 private String NL = "\n";
80 String[] a1values = new String[]{"dc=abc", "dc=prs", "dc=xyz"};
82 /** This method is called by JUnit
83 * before each test case in each test class.
86 protected final void setUp() throws Exception {
92 * Subclasses may override this method to allocate any data and resources
93 * that they need in order to successfully execute this testcase.
94 * Adding teardown classes and instances is done in the overridden method.
96 protected void localSetUp() {}
98 /** This method is called by JUnit
99 * after each test case in each test class.
102 protected final void tearDown() throws Exception {
104 // if session is null or closed, test class has already cleaned up
105 if (session != null && !(session.isClosed())) {
106 // if tx is null, get it again
108 tx = session.currentTransaction();
110 // if transaction is active (leftover), roll it back
114 // if any work to do, start a transaction and clean up
115 if (!tearDownClasses.isEmpty() | !tearDownInstances.isEmpty()) {
117 for (Class<?> cls: tearDownClasses) {
118 session.deletePersistentAll(cls);
120 for (Object o: tearDownInstances) {
121 session.deletePersistent(o);
131 * Subclasses may override this method to deallocate any data and resources
132 * that they needed in order to successfully execute this testcase.
134 protected void localTearDown() {}
136 protected void addTearDownClasses(Class... classes) {
137 for (Class cls: classes) {
138 tearDownClasses.add(cls);
142 protected Object[] dn2idPK = new Object[16];
144 public AbstractClusterJCoreTest() {
147 /** The name of the properties file; default "clusterj.properties". */
148 String PROPS_FILE_NAME = System.getProperty(
149 "clusterj.properties", "clusterj.properties");
151 /** The properties for this test run */
152 protected static Properties props;
154 /** The JDBC Driver name */
155 protected static String jdbcDriverName;
158 protected static String jdbcURL;
160 /** The JDBC Username */
161 protected static String jdbcUsername;
163 /** The JDBC Password */
164 protected static String jdbcPassword;
166 /** The JDBC Connection */
167 protected static Connection connection;
169 /** The Schema initialization statements */
170 protected static List<String> schemaDefinition = new ArrayList<String>();
172 /** Has the schema been initialized */
173 protected static boolean schemaInitialized = false;
175 /** The connection sessionFactory. */
176 protected SessionFactory sessionFactory;
178 /** The connection. Local setUp should initialize this if needed. */
179 protected Session session;
181 /** The transaction. Local setUp should initialize this if needed. */
182 protected Transaction tx;
185 * Get a connection sessionFactory.
187 protected void createSessionFactory() {
189 if (sessionFactory == null) {
190 sessionFactory = ClusterJHelper.getSessionFactory(props);
195 /** Create a file from a property name. */
196 Properties getProperties(String fileName) {
197 Properties result = null;
199 InputStream stream = new FileInputStream(new File(fileName));
200 result = new Properties();
203 } catch (FileNotFoundException ex) {
204 } catch (IOException ex) {
206 if (result == null) {
208 // try to load the resource from the class loader
209 ClassLoader cl = this.getClass().getClassLoader();
210 InputStream stream = cl.getResourceAsStream(fileName);
211 result = new Properties();
214 } catch (IOException ex) {
215 fail("Could not create ConnectionFactory " + ex);
218 return null; // not reached; fail will throw an exception
221 protected String getA1for(int number, int index) {
222 int a1factor = 1 + number/a1values.length;
223 return a1values[index/a1factor];
226 protected String getA3for(long i) {
227 return "employeenumber=100000" + i;
230 protected void setupDn2idPK() {
231 dn2idPK[0] = "dc=com";
232 // pk[1] changes and is set inside loop
233 dn2idPK[1] = "dc=example";
234 dn2idPK[2] = "ou=people";
235 // pk[3] changes and is set inside loop
250 /** Load the schema for tests */
251 protected void loadSchema() {
253 if (!schemaInitialized) {
254 loadSchemaDefinition();
261 /** Initialize the JDBC driver */
262 protected void initializeJDBC() {
267 /** Load properties from clusterj.properties */
268 protected void loadProperties() {
270 props = getProperties(PROPS_FILE_NAME);
274 /** Load JDBC driver */
275 protected void getConnection() {
276 if (connection == null) {
277 jdbcDriverName = props.getProperty(Constants.PROPERTY_JDBC_DRIVER_NAME);
278 jdbcURL = props.getProperty(Constants.PROPERTY_JDBC_URL);
279 jdbcUsername = props.getProperty(Constants.PROPERTY_JDBC_USERNAME);
280 jdbcPassword = props.getProperty(Constants.PROPERTY_JDBC_PASSWORD);
281 if (jdbcPassword == null) jdbcPassword = "";
283 Class.forName(jdbcDriverName, true, Thread.currentThread().getContextClassLoader());
284 connection = DriverManager.getConnection(jdbcURL, jdbcUsername, jdbcPassword);
285 } catch (SQLException ex) {
286 throw new ClusterJException(
287 "Exception getting connection to " + jdbcURL +
288 "; username " + jdbcUsername, ex);
289 } catch (ClassNotFoundException ex) {
290 throw new ClusterJException(
291 "Exception loading JDBC driver." + jdbcDriverName, ex);
296 protected void loadSchemaDefinition() {
297 InputStream inputStream = null;
298 StringBuffer buffer = new StringBuffer();
301 inputStream = Thread.currentThread().getContextClassLoader()
302 .getResourceAsStream("schema.sql");
303 BufferedReader reader = new BufferedReader(
304 new InputStreamReader(inputStream));
305 while (reader.ready()) {
306 line = reader.readLine();
307 if (line.contains("#")) {
308 // comment line; ignore
311 int semi = line.indexOf(";");
313 // end of sql statement; finish this statement
314 buffer.append(line.substring(0, semi));
315 schemaDefinition.add(buffer.toString());
316 buffer = new StringBuffer();
321 } catch (IOException ex) {
322 throw new ClusterJException(
323 "Exception reading schema.sql.", ex);
326 if (inputStream != null) {
329 } catch (IOException ex) {
335 protected boolean testSchema() {
337 PreparedStatement ps = connection.prepareStatement(schemaDefinition.get(0));
341 } catch (SQLException ex) {
343 "Test schema failed (normal)" + schemaDefinition.get(0));
348 /** Initialize schema definitions. */
349 protected void initializeSchema() {
350 Iterator it = schemaDefinition.iterator();
351 it.next(); // skip past condition
352 String statement = null;
354 while(it.hasNext()) {
355 statement = (String) it.next();
356 System.out.println("Executing statement " + statement + ".");
357 PreparedStatement s = connection.prepareStatement(statement);
361 schemaInitialized = true;
363 } catch (SQLException ex) {
364 throw new ClusterJException(
365 "initializeSchema threw exception on " + statement, ex);
369 protected void dumpSystemProperties() {
370 Properties sysprops =System.getProperties();
371 List<Entry<Object, Object>> entries = new ArrayList<Entry<Object, Object>>(sysprops.entrySet());
372 Collections.sort(entries, new Comparator<Entry<Object, Object>>() {
373 public int compare(Entry<Object, Object> o1, Entry<Object, Object> o2) {
374 return ((String)o1.getKey()).compareToIgnoreCase((String)o2.getKey());
377 for (Iterator<Entry<Object, Object>> iterator = entries.iterator();iterator.hasNext();) {
378 Entry<Object,Object> entry = iterator.next();
379 System.out.println("key: " + entry.getKey() + "; value: "+ entry.getValue());
383 protected void initializeErrorMessages() {
384 if (errorMessages == null) {
385 errorMessages = new StringBuffer();
386 errorMessages.append(NL);
390 protected void errorIfNotEqual(String message, Object expected, Object actual) {
391 if (!expected.equals(actual)) {
392 initializeErrorMessages();
393 errorMessages.append(message + NL);
394 errorMessages.append("Expected: " + expected.toString()
395 + " actual: " + actual.toString() + NL);
399 protected void error(String message) {
400 initializeErrorMessages();
401 errorMessages.append(message + NL);
404 protected void failOnError() {
405 if (errorMessages != null) {
406 fail(errorMessages.toString());