]> review.fuel-infra Code Review - packages/trusty/mysql-wsrep-5.6.git/blob
f624a517baf7b950485fddcfcb70c755d80b4d59
[packages/trusty/mysql-wsrep-5.6.git] /
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
55 /**
56  *
57  */
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>();
68     /** Has the schema been initialized */
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;
74     /**
75      *
76      * Error messages collected during a test.
77      */
78     private StringBuffer errorMessages;
79     /**
80      *
81      * A list of registered pc classes.
82      * The extents of these classes are deleted in <code>tearDown</code>.
83      */
84     private Collection<Class<?>> tearDownClasses = new LinkedList<Class<?>>();
85     /**
86      *
87      * A list of registered oid instances.
88      * Corresponding pc instances are deleted in <code>localTearDown</code>.
89      */
90     private Collection<Object> tearDownInstances = new LinkedList<Object>();
91
92     /**
93      *
94      * Indicates an exception thrown in method <code>tearDown</code>.
95      * At the end of method <code>tearDown</code> this field is nullified.
96      * TODO support this feature
97      */
98 //    private Throwable tearDownThrowable;
99     private String NL = "\n";
100
101     protected boolean debug;
102
103     /** Subclasses can override this method to get debugging info printed to System.out */
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
230     /** Close the connection and reset the connection variable.
231      * 
232      */
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
245     /** Get a connection with special properties. If the connection is open,
246      * close it and get a new one.
247      * 
248      */
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
269     /** Get a connection with properties from the Properties instance.
270      * 
271      */
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
286     /** Get a connection with properties from a file.
287      * 
288      * @param propertiesFileName the name of the properties file
289      */
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
302     /**
303      * @throws ClassNotFoundException
304      */
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
358     /** Initialize the JDBC driver */
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
390     /** Load properties from clusterj.properties */
391     protected void loadProperties() {
392         loadProperties(PROPS_FILE_NAME);
393     }
394
395     /** Load properties from an arbitrary file name */
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
409     /** Load the schema for tests */
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
454     /**
455      * Subclasses may override this method to allocate any data and resources
456      * that they need in order to successfully execute this testcase.
457      * Adding teardown classes and instances is done in the overridden method.
458      */
459     protected void localSetUp() {
460     }
461
462     /**
463      * Subclasses may override this method to deallocate any data and resources
464      * that they needed in order to successfully execute this testcase.
465      */
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
559     /** Catch otherwise uncaught exceptions and maintain a list of them.
560      * When needed, they can be obtained via the getUncaughtExceptions method.
561      */
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 }