You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IciqlSuite.java 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. /*
  2. * Copyright 2011 James Moger.
  3. * Copyright 2012 Frédéric Gaillard.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package com.iciql.test;
  18. import com.beust.jcommander.JCommander;
  19. import com.beust.jcommander.Parameter;
  20. import com.beust.jcommander.ParameterException;
  21. import com.beust.jcommander.Parameters;
  22. import com.iciql.Constants;
  23. import com.iciql.Db;
  24. import com.iciql.Iciql.Mode;
  25. import com.iciql.test.DataTypeAdapterTest.SerializedObjectTypeAdapterTest;
  26. import com.iciql.test.models.BooleanModel;
  27. import com.iciql.test.models.CategoryAnnotationOnly;
  28. import com.iciql.test.models.ComplexObject;
  29. import com.iciql.test.models.Customer;
  30. import com.iciql.test.models.DefaultValuesModel;
  31. import com.iciql.test.models.EnumModels.EnumIdModel;
  32. import com.iciql.test.models.EnumModels.EnumOrdinalModel;
  33. import com.iciql.test.models.EnumModels.EnumStringModel;
  34. import com.iciql.test.models.MultipleBoolsModel;
  35. import com.iciql.test.models.Order;
  36. import com.iciql.test.models.PrimitivesModel;
  37. import com.iciql.test.models.Product;
  38. import com.iciql.test.models.ProductAnnotationOnly;
  39. import com.iciql.test.models.ProductAnnotationOnlyWithForeignKey;
  40. import com.iciql.test.models.ProductInheritedAnnotation;
  41. import com.iciql.test.models.ProductMixedAnnotation;
  42. import com.iciql.test.models.ProductView;
  43. import com.iciql.test.models.ProductViewFromQuery;
  44. import com.iciql.test.models.ProductViewInherited;
  45. import com.iciql.test.models.ProductViewInheritedComplex;
  46. import com.iciql.test.models.SupportedTypes;
  47. import com.iciql.util.IciqlLogger;
  48. import com.iciql.util.IciqlLogger.IciqlListener;
  49. import com.iciql.util.IciqlLogger.StatementType;
  50. import com.iciql.util.StringUtils;
  51. import com.iciql.util.Utils;
  52. import org.apache.commons.dbcp.ConnectionFactory;
  53. import org.apache.commons.dbcp.DriverManagerConnectionFactory;
  54. import org.apache.commons.dbcp.PoolableConnectionFactory;
  55. import org.apache.commons.dbcp.PoolingDataSource;
  56. import org.apache.commons.pool.impl.GenericObjectPool;
  57. import org.apache.derby.drda.NetworkServerControl;
  58. import org.hsqldb.persist.HsqlProperties;
  59. import org.junit.Assert;
  60. import org.junit.runner.JUnitCore;
  61. import org.junit.runner.Result;
  62. import org.junit.runner.RunWith;
  63. import org.junit.runner.notification.Failure;
  64. import org.junit.runners.Suite;
  65. import org.junit.runners.Suite.SuiteClasses;
  66. import java.io.File;
  67. import java.io.FileWriter;
  68. import java.io.IOException;
  69. import java.io.PrintStream;
  70. import java.sql.SQLException;
  71. import java.text.DecimalFormat;
  72. import java.text.MessageFormat;
  73. import java.util.Arrays;
  74. import java.util.Collections;
  75. import java.util.List;
  76. import java.util.Map;
  77. /**
  78. * JUnit 4 iciql test suite.
  79. * <p>
  80. * By default this test suite will run against the H2 database. You can change
  81. * this by switching the DEFAULT_TEST_DB value.
  82. * <p>
  83. * Alternatively, you can run this class an application which will run all tests
  84. * for all tested database configurations.
  85. * <p>
  86. * NOTE: If you want to test against MySQL or PostgreSQL you must create an
  87. * "iciql" database and allow user "sa" password "sa" complete control of that
  88. * database.
  89. */
  90. @RunWith(Suite.class)
  91. @SuiteClasses({AliasMapTest.class, AnnotationsTest.class, BooleanModelTest.class, ClobTest.class,
  92. ConcurrencyTest.class, EnumsTest.class, ModelsTest.class, PrimitivesTest.class, OneOfTest.class,
  93. RuntimeQueryTest.class, SamplesTest.class, UpdateTest.class, UpgradesTest.class, JoinTest.class,
  94. UUIDTest.class, ViewsTest.class, ForeignKeyTest.class, TransactionTest.class, NestedConditionsTest.class,
  95. DataTypeAdapterTest.class, ProductDaoTest.class, BitwiseConditionTest.class})
  96. public class IciqlSuite {
  97. private final static File baseFolder = new File(System.getProperty("user.dir"), "/testdbs");
  98. private static final TestDb[] TEST_DBS = {
  99. new TestDb("H2", "memory", "jdbc:h2:mem:iciql"),
  100. new TestDb("H2", "file", "jdbc:h2:file:"
  101. + new File(baseFolder, "/h2/iciql").getAbsolutePath()),
  102. new TestDb("H2", "tcp", "jdbc:h2:tcp://localhost/"
  103. + new File(baseFolder, "/h2tcp/iciql").getAbsolutePath()),
  104. new TestDb("HSQL", "memory", "jdbc:hsqldb:mem:iciql"),
  105. new TestDb("HSQL", "file", "jdbc:hsqldb:file:testdbs/hsql/iciql"),
  106. new TestDb("HSQL", "tcp", "jdbc:hsqldb:hsql://localhost/iciql"),
  107. new TestDb("Derby", "memory", "jdbc:derby:memory:iciql;create=true"),
  108. new TestDb("Derby", "file", "jdbc:derby:directory:testdbs/derby/iciql;create=true"),
  109. new TestDb("Derby", "tcp", "jdbc:derby://localhost:1527/testdbs/derby/iciql;create=true", "sa", "sa"),
  110. new TestDb("MySQL", "tcp", "jdbc:mysql://localhost:3306/iciql?useSSL=false", "sa", "sa"),
  111. new TestDb("PostgreSQL", "tcp", "jdbc:postgresql://localhost:5432/iciql", "sa", "sa"),
  112. //
  113. // SQLite Memory
  114. //
  115. new TestDb("SQLite", "memory", "jdbc:sqlite:file::memory:?cache=shared&foreign_keys=ON"),
  116. //
  117. // SQLite DELETE rollback journal (default)
  118. //
  119. new TestDb("SQLite", "delete,full_sync", "jdbc:sqlite:"
  120. + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
  121. + "?foreign_keys=ON&journal_mode=DELETE&synchronous=FULL"),
  122. new TestDb("SQLite", "delete,norm_sync", "jdbc:sqlite:"
  123. + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
  124. + "?foreign_keys=ON&journal_mode=DELETE&synchronous=NORMAL"),
  125. new TestDb("SQLite", "delete,no_sync", "jdbc:sqlite:"
  126. + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
  127. + "?foreign_keys=ON&journal_mode=DELETE&synchronous=OFF"),
  128. //
  129. // SQLite WAL
  130. //
  131. new TestDb("SQLite", "wal,full_sync", "jdbc:sqlite:"
  132. + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
  133. + "?foreign_keys=ON&journal_mode=WAL&synchronous=FULL"),
  134. new TestDb("SQLite", "wal,norm_sync", "jdbc:sqlite:"
  135. + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
  136. + "?foreign_keys=ON&journal_mode=WAL&synchronous=NORMAL"),
  137. new TestDb("SQLite", "wal,no_sync", "jdbc:sqlite:"
  138. + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
  139. + "?foreign_keys=ON&journal_mode=WAL&synchronous=OFF"),
  140. };
  141. private static final TestDb DEFAULT_TEST_DB = TEST_DBS[3];
  142. private static final PrintStream ERR = System.err;
  143. private static PrintStream out = System.out;
  144. private static Map<String, PoolableConnectionFactory> connectionFactories = Utils
  145. .newSynchronizedHashMap();
  146. private static Map<String, PoolingDataSource> dataSources = Utils.newSynchronizedHashMap();
  147. public static void assertStartsWith(String value, String startsWith) {
  148. Assert.assertTrue(MessageFormat.format("Expected \"{0}\", got: \"{1}\"", startsWith, value),
  149. value.startsWith(startsWith));
  150. }
  151. public static void assertEqualsIgnoreCase(String expected, String actual) {
  152. Assert.assertTrue(MessageFormat.format("Expected \"{0}\", got: \"{1}\"", expected, actual),
  153. expected.equalsIgnoreCase(actual));
  154. }
  155. public static boolean equivalentTo(double expected, double actual) {
  156. if (Double.compare(expected, actual) == 0) {
  157. return true;
  158. }
  159. return Math.abs(expected - actual) <= 0.000001d;
  160. }
  161. public static Db openNewDb() {
  162. return openNewDb(Mode.PROD);
  163. }
  164. /**
  165. * Open a new Db object. All connections are cached and re-used to eliminate
  166. * embedded database startup costs.
  167. *
  168. * @param mode
  169. * @return a fresh Db object
  170. */
  171. public static Db openNewDb(Mode mode) {
  172. String testUrl = System.getProperty("iciql.url", DEFAULT_TEST_DB.url);
  173. String testUser = System.getProperty("iciql.user", DEFAULT_TEST_DB.username);
  174. String testPassword = System.getProperty("iciql.password", DEFAULT_TEST_DB.password);
  175. Db db = null;
  176. PoolingDataSource dataSource = dataSources.get(testUrl);
  177. if (dataSource == null) {
  178. ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(testUrl, testUser,
  179. testPassword);
  180. GenericObjectPool pool = new GenericObjectPool();
  181. pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW);
  182. PoolableConnectionFactory factory = new PoolableConnectionFactory(connectionFactory, pool, null,
  183. null, false, true);
  184. dataSource = new PoolingDataSource(pool);
  185. dataSources.put(testUrl, dataSource);
  186. connectionFactories.put(testUrl, factory);
  187. }
  188. db = Db.open(dataSource, mode);
  189. // drop views
  190. db.dropView(ProductView.class);
  191. db.dropView(ProductViewInherited.class);
  192. db.dropView(ProductViewFromQuery.class);
  193. db.dropView(ProductViewInheritedComplex.class);
  194. // drop tables
  195. db.dropTable(BooleanModel.class);
  196. db.dropTable(ComplexObject.class);
  197. db.dropTable(Customer.class);
  198. db.dropTable(DefaultValuesModel.class);
  199. db.dropTable(EnumIdModel.class);
  200. db.dropTable(EnumOrdinalModel.class);
  201. db.dropTable(EnumStringModel.class);
  202. db.dropTable(Order.class);
  203. db.dropTable(PrimitivesModel.class);
  204. db.dropTable(Product.class);
  205. db.dropTable(ProductAnnotationOnly.class);
  206. db.dropTable(ProductInheritedAnnotation.class);
  207. db.dropTable(ProductMixedAnnotation.class);
  208. db.dropTable(SupportedTypes.class);
  209. db.dropTable(JoinTest.UserId.class);
  210. db.dropTable(JoinTest.UserNote.class);
  211. db.dropTable(EnumsTest.BadEnums.class);
  212. db.dropTable(MultipleBoolsModel.class);
  213. db.dropTable(ProductAnnotationOnlyWithForeignKey.class);
  214. db.dropTable(CategoryAnnotationOnly.class);
  215. db.dropTable(SerializedObjectTypeAdapterTest.class);
  216. db.dropTable(ClobTest.StringRecord.class);
  217. return db;
  218. }
  219. /**
  220. * Open the current database.
  221. *
  222. * @return the current database
  223. */
  224. public static Db openCurrentDb() {
  225. String testUrl = System.getProperty("iciql.url", DEFAULT_TEST_DB.url);
  226. String testUser = System.getProperty("iciql.user", DEFAULT_TEST_DB.username);
  227. String testPassword = System.getProperty("iciql.password", DEFAULT_TEST_DB.password);
  228. return Db.open(testUrl, testUser, testPassword);
  229. }
  230. /**
  231. * Returns the name of the underlying database engine for the Db object.
  232. *
  233. * @param db
  234. * @return the database engine name
  235. */
  236. public static String getDatabaseEngineName(Db db) {
  237. String database = "";
  238. try {
  239. database = db.getConnection().getMetaData().getDatabaseProductName();
  240. } catch (SQLException s) {
  241. }
  242. return database;
  243. }
  244. /**
  245. * Returns true if the underlying database engine is Derby.
  246. *
  247. * @param db
  248. * @return true if underlying database engine is Derby
  249. */
  250. public static boolean isDerby(Db db) {
  251. return IciqlSuite.getDatabaseEngineName(db).equals("Apache Derby");
  252. }
  253. /**
  254. * Returns true if the underlying database engine is H2.
  255. *
  256. * @param db
  257. * @return true if underlying database engine is H2
  258. */
  259. public static boolean isH2(Db db) {
  260. return IciqlSuite.getDatabaseEngineName(db).equals("H2");
  261. }
  262. /**
  263. * Returns true if the underlying database engine is MySQL.
  264. *
  265. * @param db
  266. * @return true if underlying database engine is MySQL
  267. */
  268. public static boolean isMySQL(Db db) {
  269. return IciqlSuite.getDatabaseEngineName(db).equals("MySQL");
  270. }
  271. /**
  272. * Returns true if the underlying database engine is SQLite.
  273. *
  274. * @param db
  275. * @return true if underlying database engine is SQLite
  276. */
  277. public static boolean isSQLite(Db db) {
  278. return IciqlSuite.getDatabaseEngineName(db).equals("SQLite");
  279. }
  280. /**
  281. * Gets the default schema of the underlying database engine.
  282. *
  283. * @param db
  284. * @return the default schema
  285. */
  286. public static String getDefaultSchema(Db db) {
  287. if (isDerby(db)) {
  288. // Derby sets default schema name to username
  289. return "SA";
  290. } else if (isMySQL(db)) {
  291. // MySQL does not have schemas
  292. return null;
  293. } else if (isSQLite(db)) {
  294. // SQLite does not have schemas
  295. return null;
  296. }
  297. return "PUBLIC";
  298. }
  299. /**
  300. * Main entry point for the test suite. Executing this method will run the
  301. * test suite on all registered databases.
  302. *
  303. * @param args
  304. * @throws Exception
  305. */
  306. public static void main(String... args) throws Exception {
  307. Params params = new Params();
  308. JCommander jc = new JCommander(params);
  309. try {
  310. jc.parse(args);
  311. } catch (ParameterException t) {
  312. usage(jc, t);
  313. }
  314. // Replace System.out with a file
  315. if (!StringUtils.isNullOrEmpty(params.dbPerformanceFile)) {
  316. out = new PrintStream(params.dbPerformanceFile);
  317. System.setErr(out);
  318. }
  319. deleteRecursively(baseFolder);
  320. new File(baseFolder, "/sqlite").mkdirs();
  321. // Start the HSQL, H2, and Derby servers in-process
  322. org.hsqldb.Server hsql = startHSQL();
  323. org.h2.tools.Server h2 = startH2();
  324. NetworkServerControl derby = startDerby();
  325. // Statement logging
  326. final FileWriter statementWriter;
  327. if (StringUtils.isNullOrEmpty(params.sqlStatementsFile)) {
  328. statementWriter = null;
  329. } else {
  330. statementWriter = new FileWriter(params.sqlStatementsFile);
  331. }
  332. IciqlListener statementListener = new IciqlListener() {
  333. @Override
  334. public void logIciql(StatementType type, String statement) {
  335. if (statementWriter == null) {
  336. return;
  337. }
  338. try {
  339. statementWriter.append(statement);
  340. statementWriter.append('\n');
  341. } catch (IOException e) {
  342. e.printStackTrace();
  343. }
  344. }
  345. };
  346. IciqlLogger.registerListener(statementListener);
  347. SuiteClasses suiteClasses = IciqlSuite.class.getAnnotation(SuiteClasses.class);
  348. long quickestDatabase = Long.MAX_VALUE;
  349. String dividerMajor = buildDivider('*', 79);
  350. String dividerMinor = buildDivider('-', 79);
  351. // Header
  352. out.println(dividerMajor);
  353. out.println(MessageFormat.format("{0} {1} ({2}) testing {3} database configurations", Constants.NAME,
  354. Constants.getVersion(), Constants.getBuildDate(), TEST_DBS.length));
  355. out.println(dividerMajor);
  356. out.println();
  357. showProperty("java.vendor");
  358. showProperty("java.runtime.version");
  359. showProperty("java.vm.name");
  360. showProperty("os.name");
  361. showProperty("os.version");
  362. showProperty("os.arch");
  363. showProperty("available processors", "" + Runtime.getRuntime().availableProcessors());
  364. showProperty(
  365. "available memory",
  366. MessageFormat.format("{0,number,0.0} GB", ((double) Runtime.getRuntime().maxMemory())
  367. / (1024 * 1024)));
  368. out.println();
  369. // Test a database
  370. long lastCount = 0;
  371. for (TestDb testDb : TEST_DBS) {
  372. out.println(dividerMinor);
  373. out.println("Testing " + testDb.describeDatabase());
  374. out.println(" " + testDb.url);
  375. out.println(dividerMinor);
  376. // inject a database section delimiter in the statement log
  377. if (statementWriter != null) {
  378. statementWriter.append("\n\n");
  379. statementWriter.append("# ").append(dividerMinor).append('\n');
  380. statementWriter.append("# ").append("Testing " + testDb.describeDatabase()).append('\n');
  381. statementWriter.append("# ").append(dividerMinor).append('\n');
  382. statementWriter.append("\n\n");
  383. }
  384. if (testDb.getVersion().equals("OFFLINE")) {
  385. // Database not available
  386. out.println("Skipping. Could not find " + testDb.url);
  387. out.println();
  388. } else {
  389. // Setup system properties
  390. System.setProperty("iciql.url", testDb.url);
  391. System.setProperty("iciql.user", testDb.username);
  392. System.setProperty("iciql.password", testDb.password);
  393. // Test database
  394. Result result = JUnitCore.runClasses(suiteClasses.value());
  395. // Report results
  396. testDb.runtime = result.getRunTime();
  397. if (testDb.runtime < quickestDatabase) {
  398. quickestDatabase = testDb.runtime;
  399. }
  400. testDb.statements = IciqlLogger.getTotalCount() - lastCount;
  401. // reset total count for next database
  402. lastCount = IciqlLogger.getTotalCount();
  403. out.println(MessageFormat.format(
  404. "{0} tests ({1} failures, {2} ignores) {3} statements in {4,number,0.000} secs",
  405. result.getRunCount(), result.getFailureCount(), result.getIgnoreCount(),
  406. testDb.statements, result.getRunTime() / 1000f));
  407. if (result.getFailureCount() == 0) {
  408. out.println();
  409. out.println(" 100% successful test suite run.");
  410. out.println();
  411. } else {
  412. for (Failure failure : result.getFailures()) {
  413. out.println(MessageFormat.format("\n + {0}\n {1}", failure.getTestHeader(),
  414. failure.getMessage()));
  415. }
  416. out.println();
  417. }
  418. }
  419. }
  420. // Display runtime results sorted by performance leader
  421. out.println();
  422. out.println(dividerMajor);
  423. out.println(MessageFormat.format("{0} {1} ({2}) test suite performance results", Constants.NAME,
  424. Constants.getVersion(), Constants.getBuildDate()));
  425. StringBuilder compressedSystem = new StringBuilder();
  426. compressedSystem.append(" on ");
  427. compressedSystem.append(System.getProperty("java.vendor"));
  428. compressedSystem.append(' ');
  429. compressedSystem.append(System.getProperty("java.runtime.version"));
  430. compressedSystem.append(", ");
  431. compressedSystem.append(System.getProperty("os.name"));
  432. compressedSystem.append(' ');
  433. compressedSystem.append(System.getProperty("os.version"));
  434. compressedSystem.append(", ");
  435. compressedSystem.append(System.getProperty("os.arch"));
  436. out.println(compressedSystem.toString());
  437. out.println(dividerMajor);
  438. List<TestDb> dbs = Arrays.asList(TEST_DBS);
  439. Collections.sort(dbs);
  440. out.println(MessageFormat.format("{0} {1} {2} {3} {4}",
  441. StringUtils.pad("Name", 11, " ", true),
  442. StringUtils.pad("Config", 16, " ", true),
  443. StringUtils.pad("Version", 25, " ", true),
  444. StringUtils.pad("Stats/sec", 10, " ", true),
  445. "Runtime"));
  446. out.println(dividerMinor);
  447. for (TestDb testDb : dbs) {
  448. DecimalFormat df = new DecimalFormat("0.0");
  449. out.println(MessageFormat.format("{0} {1} {2} {3} {4}s ({5,number,0.0}x)",
  450. StringUtils.pad(testDb.name, 11, " ", true),
  451. StringUtils.pad(testDb.config, 16, " ", true),
  452. StringUtils.pad(testDb.getVersion(), 23, " ", true),
  453. StringUtils.pad("" + testDb.getStatementRate(), 7, " ", false),
  454. StringUtils.pad(df.format(testDb.getRuntime()), 8, " ", false),
  455. ((double) testDb.runtime) / quickestDatabase));
  456. }
  457. out.println(dividerMinor);
  458. // cleanup
  459. for (PoolableConnectionFactory factory : connectionFactories.values()) {
  460. factory.getPool().close();
  461. }
  462. IciqlLogger.unregisterListener(statementListener);
  463. out.close();
  464. System.setErr(ERR);
  465. if (statementWriter != null) {
  466. statementWriter.close();
  467. }
  468. hsql.stop();
  469. h2.stop();
  470. derby.shutdown();
  471. System.exit(0);
  472. }
  473. private static void showProperty(String name) {
  474. showProperty(name, System.getProperty(name));
  475. }
  476. private static void showProperty(String name, String value) {
  477. out.print(' ');
  478. out.print(StringUtils.pad(name, 25, " ", true));
  479. out.println(value);
  480. }
  481. private static void usage(JCommander jc, ParameterException t) {
  482. System.out.println(Constants.NAME + " test suite v" + Constants.getVersion());
  483. System.out.println();
  484. if (t != null) {
  485. System.out.println(t.getMessage());
  486. System.out.println();
  487. }
  488. if (jc != null) {
  489. jc.usage();
  490. }
  491. System.exit(0);
  492. }
  493. private static String buildDivider(char c, int length) {
  494. StringBuilder sb = new StringBuilder();
  495. for (int i = 0; i < length; i++) {
  496. sb.append(c);
  497. }
  498. return sb.toString();
  499. }
  500. private static void deleteRecursively(File f) {
  501. if (f.isDirectory()) {
  502. for (File file : f.listFiles()) {
  503. if (file.isDirectory()) {
  504. deleteRecursively(file);
  505. }
  506. file.delete();
  507. }
  508. }
  509. f.delete();
  510. }
  511. /**
  512. * Start an HSQL tcp server.
  513. *
  514. * @return an HSQL server instance
  515. * @throws Exception
  516. */
  517. private static org.hsqldb.Server startHSQL() throws Exception {
  518. HsqlProperties p = new HsqlProperties();
  519. String db = new File(System.getProperty("user.dir")).getAbsolutePath() + "/testdbs/hsqltcp/iciql";
  520. p.setProperty("server.database.0", "file:" + db);
  521. p.setProperty("server.dbname.0", "iciql");
  522. // set up the rest of properties
  523. // alternative to the above is
  524. org.hsqldb.Server server = new org.hsqldb.Server();
  525. server.setProperties(p);
  526. server.setLogWriter(null);
  527. server.setErrWriter(null);
  528. server.start();
  529. return server;
  530. }
  531. /**
  532. * Start the H2 tcp server.
  533. *
  534. * @return an H2 server instance
  535. * @throws Exception
  536. */
  537. private static org.h2.tools.Server startH2() throws Exception {
  538. org.h2.tools.Server server = org.h2.tools.Server.createTcpServer();
  539. server.start();
  540. return server;
  541. }
  542. /**
  543. * Start the Derby tcp server.
  544. *
  545. * @return an Derby server instance
  546. * @throws Exception
  547. */
  548. private static NetworkServerControl startDerby() throws Exception {
  549. NetworkServerControl serverControl = new NetworkServerControl();
  550. serverControl.start(null);
  551. return serverControl;
  552. }
  553. /**
  554. * Represents a test database url.
  555. */
  556. private static class TestDb implements Comparable<TestDb> {
  557. final String name;
  558. final String config;
  559. final String url;
  560. final String username;
  561. final String password;
  562. String version;
  563. long runtime;
  564. long statements;
  565. TestDb(String name, String config, String url) {
  566. this(name, config, url, "sa", "");
  567. }
  568. TestDb(String name, String config, String url, String username, String password) {
  569. this.name = name;
  570. this.config = config;
  571. this.url = url;
  572. this.username = username;
  573. this.password = password;
  574. }
  575. double getRuntime() {
  576. return runtime / 1000d;
  577. }
  578. int getStatementRate() {
  579. return Double.valueOf((statements) / (runtime / 1000d)).intValue();
  580. }
  581. String describeDatabase() {
  582. StringBuilder sb = new StringBuilder(name);
  583. sb.append(" ");
  584. sb.append(getVersion());
  585. return sb.toString();
  586. }
  587. String getVersion() {
  588. if (version == null) {
  589. try {
  590. Db db = Db.open(url, username, password);
  591. version = db.getConnection().getMetaData().getDatabaseProductVersion();
  592. db.close();
  593. return version;
  594. } catch (Throwable t) {
  595. version = "OFFLINE";
  596. }
  597. }
  598. return version;
  599. }
  600. @Override
  601. public int compareTo(TestDb o) {
  602. if (runtime == 0) {
  603. return 1;
  604. }
  605. if (o.runtime == 0) {
  606. return -1;
  607. }
  608. int r1 = getStatementRate();
  609. int r2 = o.getStatementRate();
  610. if (r1 == r2) {
  611. return 0;
  612. }
  613. if (r1 < r2) {
  614. return 1;
  615. }
  616. return -1;
  617. }
  618. }
  619. /**
  620. * Command-line parameters for TestSuite.
  621. */
  622. @Parameters(separators = " ")
  623. private static class Params {
  624. @Parameter(names = {"--dbFile"}, description = "Database performance results text file", required = false)
  625. public String dbPerformanceFile;
  626. @Parameter(names = {"--sqlFile"}, description = "SQL statements log file", required = false)
  627. public String sqlStatementsFile;
  628. }
  629. }