MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AbstractClusterJTest.java
1 /*
2  Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
3 
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.
7 
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.
12 
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
16 */
17 
18 package testsuite.clusterj;
19 
20 import com.mysql.clusterj.ClusterJException;
21 import com.mysql.clusterj.ClusterJHelper;
22 import com.mysql.clusterj.Constants;
23 import com.mysql.clusterj.Session;
24 import com.mysql.clusterj.SessionFactory;
25 import com.mysql.clusterj.Transaction;
26 
27 import java.io.BufferedReader;
28 import java.io.File;
29 import java.io.FileInputStream;
30 import java.io.FileNotFoundException;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.InputStreamReader;
34 import java.lang.Thread.UncaughtExceptionHandler;
35 
36 import java.sql.Connection;
37 import java.sql.DriverManager;
38 import java.sql.PreparedStatement;
39 import java.sql.SQLException;
40 import java.sql.Statement;
41 
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.Collection;
45 import java.util.Collections;
46 import java.util.Comparator;
47 import java.util.Iterator;
48 import java.util.LinkedList;
49 import java.util.List;
50 import java.util.Map.Entry;
51 import java.util.Properties;
52 
53 import junit.framework.TestCase;
54 
58 public abstract class AbstractClusterJTest extends TestCase {
59  protected static final String JDBC_DRIVER_NAME = "jdbc.driverName";
60  protected static final String JDBC_URL = "jdbc.url";
61  protected static Connection connection;
62  protected static String jdbcDriverName;
63  protected static String jdbcPassword;
64  protected static String jdbcURL;
65  protected static String jdbcUsername;
66  protected static Properties props;
67  protected static List<String> schemaDefinition = new ArrayList<String>();
69  protected static boolean schemaInitialized = false;
70  String PROPS_FILE_NAME = System.getProperty("clusterj.properties", "clusterj.properties");
71  protected Session session;
72  protected SessionFactory sessionFactory;
73  protected Transaction tx;
78  private StringBuffer errorMessages;
84  private Collection<Class<?>> tearDownClasses = new LinkedList<Class<?>>();
90  private Collection<Object> tearDownInstances = new LinkedList<Object>();
91 
98 // private Throwable tearDownThrowable;
99  private String NL = "\n";
100 
101  protected boolean debug;
102 
104  protected boolean getDebug() {
105  return false;
106  }
107 
108  public AbstractClusterJTest() {
109  debug = getDebug();
110  }
111 
112  protected void addTearDownClasses(Class<?>... classes) {
113  for (Class<?> cls : classes) {
114  tearDownClasses.add(cls);
115  }
116  }
117 
118  protected void createSessionFactory() {
119  if (sessionFactory == null) {
120  loadProperties();
121  Properties modifiedProperties = modifyProperties();
122  if (debug) System.out.println("createSessionFactory props: " + modifiedProperties);
123  sessionFactory = ClusterJHelper.getSessionFactory(modifiedProperties);
124  loadSchema();
125  }
126  }
127 
128  protected Properties modifyProperties() {
129  // doesn't do anything but can be overridden by a subclass
130  return props;
131  }
132 
133  public void createSession() {
134  if (session != null && !session.isClosed()) {
135  tx = session.currentTransaction();
136  if (tx.isActive()) {
137  tx.commit();
138  }
139  session.close();
140  }
141  session = sessionFactory.getSession();
142  tx = session.currentTransaction();
143  }
144 
145  protected void dumpSystemProperties() {
146  Properties sysprops = System.getProperties();
147  List<Entry<Object, Object>> entries = new ArrayList<Entry<Object, Object>>(sysprops.entrySet());
148  Collections.sort(entries, new Comparator<Entry<Object, Object>>() {
149 
150  public int compare(Entry<Object, Object> o1, Entry<Object, Object> o2) {
151  return ((String) o1.getKey()).compareToIgnoreCase((String) o2.getKey());
152  }
153  });
154  for (Iterator<Entry<Object, Object>> iterator = entries.iterator(); iterator.hasNext();) {
155  Entry<Object, Object> entry = iterator.next();
156  System.out.println("key: " + entry.getKey() + "; value: " + entry.getValue());
157  }
158  }
159 
160  protected void error(String message) {
161  initializeErrorMessages();
162  errorMessages.append(message + NL);
163  }
164 
165  protected void error(String context, Exception ex) {
166  String message = context + " " + ex.getClass().getName() + ":" + ex.getMessage();
167  error(message);
168  if (getDebug()) {
169  ex.printStackTrace();
170  }
171  }
172 
173  protected void errorIfNotEqual(String message, Object expected, Object actual) {
174  if (expected == null && actual == null) {
175  return;
176  }
177  if (expected != null && expected.equals(actual)) {
178  return;
179  } else {
180  initializeErrorMessages();
181  errorMessages.append(message + NL);
182  errorMessages.append(
183  "Expected: " + ((expected==null)?"null":expected.toString())
184  + " actual: " + ((actual==null)?"null":actual.toString()) + NL);
185  }
186  }
187 
188  protected void errorIfNotEqual(String message, int[] expected, int[] actual) {
189  if (expected == null && actual == null) {
190  return;
191  }
192  int i;
193  if (expected.length == actual.length) {
194  for (i = 0; i < expected.length; ++i) {
195  if (expected[i] != actual[i]) {
196  break;
197  }
198  }
199  if (i == expected.length) {
200  return;
201  }
202  }
203  initializeErrorMessages();
204  errorMessages.append(message + NL);
205  errorMessages.append(
206  "Expected: " + ((expected==null)?"null":Arrays.toString(expected))
207  + " actual: " + ((actual==null)?"null":Arrays.toString(actual)) + NL);
208  }
209 
210  protected void errorIfEqual(String message, Object expected, Object actual) {
211  if (expected == null && actual != null) {
212  return;
213  }
214  if (expected != null && !expected.equals(actual)) {
215  return;
216  } else {
217  initializeErrorMessages();
218  errorMessages.append(message + NL);
219  errorMessages.append(
220  "Error value: " + ((expected==null)?"null":expected.toString()));
221  }
222  }
223 
224  protected void failOnError() {
225  if (errorMessages != null) {
226  fail(errorMessages.toString());
227  }
228  }
229 
233  protected void closeConnection() {
234  try {
235  if (connection != null) {
236  connection.close();
237  }
238  } catch (SQLException e) {
239  throw new RuntimeException("Caught SQLException during close.", e);
240  } finally {
241  connection = null;
242  }
243  }
244 
249  protected void getConnection(Properties extraProperties) {
250  // characterEncoding = utf8 property is especially useful
251  Properties properties = new Properties();
252  properties.put("user", jdbcUsername);
253  properties.put("password", jdbcPassword);
254  properties.putAll(extraProperties);
255  try {
256  if (connection != null && !connection.isClosed()) {
257  connection.close();
258  connection = null;
259  }
260  if (debug) System.out.println("Getting new connection with properties " + properties);
261  connection = DriverManager.getConnection(jdbcURL, properties);
262  } catch (SQLException ex) {
263  ex.printStackTrace();
264  throw new ClusterJException("Exception getting connection to " + jdbcURL + "; username " + jdbcUsername, ex);
265  // TODO Auto-generated catch block
266  }
267  }
268 
272  protected Connection getConnection() {
273  if (connection == null) {
274  try {
275  Class.forName(jdbcDriverName, true, Thread.currentThread().getContextClassLoader());
276  connection = DriverManager.getConnection(jdbcURL, jdbcUsername, jdbcPassword);
277  } catch (SQLException ex) {
278  throw new ClusterJException("Exception getting connection to " + jdbcURL + "; username " + jdbcUsername, ex);
279  } catch (ClassNotFoundException ex) {
280  throw new ClusterJException("Exception loading JDBC driver." + jdbcDriverName, ex);
281  }
282  }
283  return connection;
284  }
285 
290  protected void getConnection(String propertiesFileName) {
291  loadProperties(propertiesFileName);
292  loadDriver();
293  String url = props.getProperty(JDBC_URL);
294  try {
295  connection = DriverManager.getConnection(url);
296  setAutoCommit(connection, false);
297  } catch (SQLException e) {
298  throw new RuntimeException("Could not get Connection: " + url, e);
299  }
300  }
301 
305  protected void loadDriver() {
306  String driverName = props.getProperty(JDBC_DRIVER_NAME);
307  try {
308  Class.forName(driverName);
309  } catch (ClassNotFoundException e) {
310  throw new RuntimeException("Class not found: " + driverName, e);
311  }
312  }
313 
314  protected void setAutoCommit(Connection connection, boolean b) {
315  try {
316  connection.setAutoCommit(false);
317  } catch (SQLException e) {
318  throw new RuntimeException("setAutoCommit failed", e);
319  }
320  }
321 
322  Properties getProperties(String fileName) {
323  Properties result = null;
324  try {
325  InputStream stream = new FileInputStream(new File(fileName));
326  result = new Properties();
327  result.load(stream);
328  return result;
329  } catch (FileNotFoundException ex) {
330  // ignore and try getResourceAsStream
331  } catch (IOException ex) {
332  // ignore and try getResourceAsStream
333  }
334  if (result == null) {
335  try {
336  // try to load the resource from the class loader
337  ClassLoader cl = this.getClass().getClassLoader();
338  InputStream stream = cl.getResourceAsStream(fileName);
339  result = new Properties();
340  result.load(stream);
341  return result;
342  } catch (IOException ex) {
343  fail("Could not create ConnectionFactory " + ex);
344  } catch (NullPointerException ex) {
345  fail("Missing properties file " + fileName);
346  }
347  }
348  return null;
349  }
350 
351  protected void initializeErrorMessages() {
352  if (errorMessages == null) {
353  errorMessages = new StringBuffer();
354  errorMessages.append(NL);
355  }
356  }
357 
359  protected void initializeJDBC() {
360  loadProperties();
361  getConnection();
362  }
363 
364  protected void initializeSchema() {
365  getConnection();
366  Iterator<String> it = schemaDefinition.iterator();
367  // skip past drop table
368  it.next();
369  // skip past test table
370  it.next();
371  String statement = null;
372  try {
373  while (it.hasNext()) {
374  statement = it.next();
375  if (debug) System.out.println("Executing statement " + statement + ";");
376  PreparedStatement s = connection.prepareStatement(statement);
377  s.execute();
378  s.close();
379  }
380  schemaInitialized = true;
381 // connection.close();
382  System.out.println("Successfully initialized schema.");
383  } catch (SQLException ex) {
384  // on failure, drop the test table so we try again
385  resetSchema();
386  throw new ClusterJException("initializeSchema threw exception on " + statement, ex);
387  }
388  }
389 
391  protected void loadProperties() {
392  loadProperties(PROPS_FILE_NAME);
393  }
394 
396  protected void loadProperties(String propsFileName) {
397 // if (props == null) {
398  props = getProperties(propsFileName);
399 // }
400  jdbcDriverName = props.getProperty(Constants.PROPERTY_JDBC_DRIVER_NAME);
401  jdbcURL = props.getProperty(Constants.PROPERTY_JDBC_URL);
402  jdbcUsername = props.getProperty(Constants.PROPERTY_JDBC_USERNAME);
403  jdbcPassword = props.getProperty(Constants.PROPERTY_JDBC_PASSWORD);
404  if (jdbcPassword == null) {
405  jdbcPassword = "";
406  }
407  }
408 
410  protected void loadSchema() {
411  initializeJDBC();
412  if (!schemaInitialized) {
413  loadSchemaDefinition();
414  if (!testSchema()) {
415  initializeSchema();
416  }
417  }
418  }
419 
420  protected void loadSchemaDefinition() {
421  InputStream inputStream = null;
422  StringBuffer buffer = new StringBuffer();
423  String line;
424  try {
425  inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("schema.sql");
426  BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
427  while (reader.ready()) {
428  line = reader.readLine();
429  if (line.contains("#")) {
430  // comment line; ignore
431  continue;
432  }
433  int semi = line.indexOf(";");
434  if (semi != -1) {
435  buffer.append(line.substring(0, semi));
436  schemaDefinition.add(buffer.toString());
437  buffer = new StringBuffer();
438  } else {
439  buffer.append(line);
440  }
441  }
442  } catch (IOException ex) {
443  throw new ClusterJException("Exception reading schema.sql.", ex);
444  } finally {
445  try {
446  if (inputStream != null) {
447  inputStream.close();
448  }
449  } catch (IOException ex) {
450  }
451  }
452  }
453 
459  protected void localSetUp() {
460  }
461 
466  protected void localTearDown() {
467  }
468 
469  @Override
470  protected final void setUp() throws Exception {
471  localSetUp();
472  }
473 
474  @Override
475  protected final void tearDown() throws Exception {
476  localTearDown();
477  // if session is null or closed, test class has already cleaned up
478  if (session != null && !(session.isClosed())) {
479  // if tx is null, get it again
480  if (tx == null) {
481  tx = session.currentTransaction();
482  }
483  // if transaction is active (leftover), roll it back
484  if (tx.isActive()) {
485  tx.rollback();
486  }
487  // if any work to do, start a transaction and clean up
488  if (!tearDownClasses.isEmpty() | !tearDownInstances.isEmpty()) {
489  tx.begin();
490  for (Class<?> cls : tearDownClasses) {
491  session.deletePersistentAll(cls);
492  }
493  for (Object o : tearDownInstances) {
494  session.deletePersistent(o);
495  }
496  tx.commit();
497  session.close();
498  session = null;
499  }
500  }
501  session = null;
502  sessionFactory = null;
503  }
504 
505  protected void removeAll(Class<?> cls) {
506  sessionFactory.getSession();
507  session.currentTransaction().begin();
508  session.deletePersistentAll(cls);
509  session.currentTransaction().commit();
510  }
511 
512  protected boolean testSchema() {
513  try {
514  Statement statement = connection.createStatement();
515  statement.execute(schemaDefinition.get(1));
516  statement.close();
517  return true;
518  } catch (SQLException ex) {
519  if (debug) {
520  ex.printStackTrace();
521  }
522  System.out.println("Test schema failed (normal) " + schemaDefinition.get(1));
523  return false;
524  }
525  }
526 
527  protected boolean resetSchema() {
528  try {
529  Statement statement = connection.createStatement();
530  statement.execute(schemaDefinition.get(0));
531  statement.close();
532  return true;
533  } catch (SQLException ex) {
534  System.out.println("Test schema failed (normal) " + schemaDefinition.get(0));
535  return false;
536  }
537  }
538 
539  protected static String dump(String string) {
540  StringBuffer buffer = new StringBuffer("[");
541  for (int i = 0; i < string.length(); ++i) {
542  int theCharacter = string.charAt(i);
543  buffer.append(theCharacter);
544  buffer.append(" ");
545  }
546  buffer.append("]");
547  return buffer.toString();
548  }
549 
550  protected String dump(List<String> list) {
551  StringBuffer result = new StringBuffer();
552  for (String string: list) {
553  result.append(dump(string));
554  result.append('\n');
555  }
556  return result.toString();
557  }
558 
562  public static class MyUncaughtExceptionHandler implements UncaughtExceptionHandler {
563  private static List<Throwable> uncaughtExceptions = new ArrayList<Throwable>();
564  public List<Throwable> getUncaughtExceptions() {
565  return uncaughtExceptions;
566  }
567  public synchronized void uncaughtException(Thread t, Throwable e) {
568  {
569  uncaughtExceptions.add(e);
570  }
571  }
572  }
573 
574 }