/activeobjects-plugin/src/test/java/com/atlassian/activeobjects/backup/ActiveObjectsBackupDataSetup.java

https://bitbucket.org/activeobjects/ao-plugin · Java · 344 lines · 282 code · 62 blank · 0 comment · 26 complexity · 403109b1326a8dde3fa39459369a16a7 MD5 · raw file

  1. package com.atlassian.activeobjects.backup;
  2. import com.atlassian.activeobjects.test.model.Model;
  3. import com.google.common.collect.ImmutableList;
  4. import com.google.common.collect.ImmutableMap;
  5. import net.java.ao.DatabaseProvider;
  6. import net.java.ao.db.H2DatabaseProvider;
  7. import net.java.ao.db.HSQLDatabaseProvider;
  8. import net.java.ao.db.MsJdbcSQLServerDatabaseProvider;
  9. import net.java.ao.db.MySQLDatabaseProvider;
  10. import net.java.ao.db.OracleDatabaseProvider;
  11. import net.java.ao.db.PostgreSQLDatabaseProvider;
  12. import net.java.ao.db.SQLServerDatabaseProvider;
  13. import org.custommonkey.xmlunit.SimpleNamespaceContext;
  14. import org.custommonkey.xmlunit.XMLUnit;
  15. import org.custommonkey.xmlunit.XpathEngine;
  16. import org.custommonkey.xmlunit.exceptions.XpathException;
  17. import org.junit.After;
  18. import org.junit.Before;
  19. import org.w3c.dom.Document;
  20. import org.w3c.dom.Node;
  21. import org.w3c.dom.NodeList;
  22. import java.sql.Types;
  23. import static net.java.ao.Common.fuzzyTypeCompare;
  24. import static org.custommonkey.xmlunit.XMLAssert.assertEquals;
  25. import static org.hamcrest.MatcherAssert.assertThat;
  26. import static org.hamcrest.Matchers.is;
  27. public abstract class ActiveObjectsBackupDataSetup extends AbstractTestActiveObjectsBackup {
  28. protected static final String H2 = "/com/atlassian/activeobjects/backup/h2.xml";
  29. protected static final String HSQL = "/com/atlassian/activeobjects/backup/hsql.xml";
  30. protected static final String HSQL_EMPTY = "/com/atlassian/activeobjects/backup/hsql_empty.xml";
  31. protected static final String MYSQL = "/com/atlassian/activeobjects/backup/mysql.xml";
  32. protected static final String ORACLE = "/com/atlassian/activeobjects/backup/oracle.xml";
  33. protected static final String LEGACY_ORACLE = "/com/atlassian/activeobjects/backup/legacy_oracle.xml";
  34. protected static final String POSTGRES = "/com/atlassian/activeobjects/backup/postgres.xml";
  35. protected static final String SQLSERVER_JTDS = "/com/atlassian/activeobjects/backup/sqlserver_jtds.xml";
  36. protected static final String SQLSERVER_MSJDBC = "/com/atlassian/activeobjects/backup/sqlserver_msjdbc.xml";
  37. private Model model;
  38. protected final void testBackup(String xml, Iterable<BackupData> data) throws Exception {
  39. final String xmlBackup = read(xml);
  40. checkXmlBackup(xmlBackup, data);
  41. restore(xmlBackup);
  42. restore(xmlBackup); // if we don't clean up correctly doing an second restore in a row will fail
  43. assertDataPresent();
  44. final String secondXmlBackup = save();
  45. checkXmlBackup(secondXmlBackup, getCurrentDatabaseData());
  46. }
  47. private Iterable<BackupData> getCurrentDatabaseData() {
  48. final DatabaseProvider provider = entityManager.getProvider();
  49. if (provider.getClass() == H2DatabaseProvider.class) {
  50. return H2_DATA;
  51. } else if (provider.getClass() == HSQLDatabaseProvider.class) {
  52. return HSQL_DATA;
  53. } else if (provider.getClass() == MySQLDatabaseProvider.class) {
  54. return MYSQL_DATA;
  55. } else if (provider.getClass() == PostgreSQLDatabaseProvider.class) {
  56. return POSTGRES_DATA;
  57. } else if (provider.getClass() == OracleDatabaseProvider.class) {
  58. return ORACLE_DATA;
  59. } else if (provider.getClass() == SQLServerDatabaseProvider.class) {
  60. return SQL_SERVER_DATA_JTDS;
  61. } else if (provider.getClass() == MsJdbcSQLServerDatabaseProvider.class) {
  62. return SQL_SERVER_DATA_MSJDBC;
  63. } else {
  64. throw new IllegalStateException("Can't figure out which DB we're testing against!");
  65. }
  66. }
  67. protected void checkXmlBackup(String xmlBackup, Iterable<BackupData> data) throws Exception {
  68. final XpathEngine engine = newXpathEngine();
  69. final Document doc = XMLUnit.buildControlDocument(xmlBackup);
  70. for (BackupData bd : data) {
  71. assertHasBackupData(engine, doc, bd);
  72. }
  73. }
  74. private void assertHasBackupData(XpathEngine xpathEngine, Document xmlBackupDoc, BackupData bd) throws Exception {
  75. assertHasColumn(xpathEngine, xmlBackupDoc, bd.table, bd.column, bd.primaryKey, bd.autoIncrement, bd.sqlType);
  76. }
  77. private void assertHasColumn(XpathEngine xpathEngine, Document xmlBackupDoc, String tableName, String columnName, boolean pK, boolean autoIncrement, SqlType sqlType) throws XpathException {
  78. NodeList tableNodes = xpathEngine.getMatchingNodes("/ao:backup/ao:table[@name='" + tableName + "']/ao:column[@name='" + columnName + "']", xmlBackupDoc);
  79. assertEquals(1, tableNodes.getLength());
  80. Node table = tableNodes.item(0);
  81. assertAttributeEquals("Expected " + tableName + "." + columnName + " to " + (pK ? "" : "NOT ") + "be a primary key.", table, "primaryKey", pK);
  82. assertAttributeEquals("Expected " + tableName + "." + columnName + " to " + (autoIncrement ? "" : "NOT ") + "be auto increment.", table, "autoIncrement", autoIncrement);
  83. assertThat("Expected " + tableName + "." + columnName + " to be of SQL Type: " + sqlType.type,
  84. fuzzyTypeCompare(sqlType.type, Integer.valueOf(attributeValue(table, "sqlType"))), is(true));
  85. if (sqlType.precision != null) {
  86. assertAttributeEquals("Expected " + tableName + "." + columnName + " to have precision: " + sqlType.precision, table, "precision", sqlType.precision);
  87. }
  88. if (sqlType.scale != null) {
  89. assertAttributeEquals("Expected " + tableName + "." + columnName + " to have scale: " + sqlType.scale, table, "scale", sqlType.scale);
  90. }
  91. assertEquals(1, xpathEngine.getMatchingNodes("/ao:backup/ao:data[@tableName='" + tableName + "']/ao:column[@name='" + columnName + "']", xmlBackupDoc).getLength());
  92. }
  93. private void assertAttributeEquals(String message, Node table, String attribute, Object expected) {
  94. assertEquals(message, String.valueOf(expected), attributeValue(table, attribute));
  95. }
  96. private XpathEngine newXpathEngine() {
  97. XpathEngine engine = XMLUnit.newXpathEngine();
  98. engine.setNamespaceContext(new SimpleNamespaceContext(ImmutableMap.of("ao", "http://www.atlassian.com/ao")));
  99. return engine;
  100. }
  101. private String attributeValue(Node node, String name) {
  102. return node.getAttributes().getNamedItem(name).getNodeValue();
  103. }
  104. private void assertDataPresent() {
  105. model.checkAuthors();
  106. model.checkBooks();
  107. }
  108. @Before
  109. public void setUpModel() {
  110. model = new Model(entityManager);
  111. model.emptyDatabase();
  112. }
  113. @After
  114. public void tearDownModel() {
  115. model = null;
  116. }
  117. private static final class BackupData {
  118. public final String table, column;
  119. public final boolean primaryKey;
  120. public final boolean autoIncrement;
  121. public final SqlType sqlType;
  122. public BackupData(String table, String column, boolean primaryKey, boolean autoIncrement, SqlType sqlType) {
  123. this.table = table;
  124. this.column = column;
  125. this.sqlType = sqlType;
  126. this.primaryKey = primaryKey;
  127. this.autoIncrement = autoIncrement;
  128. }
  129. static BackupData of(String table, String column, SqlType sqlType) {
  130. return of(table, column, sqlType, false, false);
  131. }
  132. static BackupData of(String table, String column, SqlType sqlType, boolean primaryKey, boolean autoIncrement) {
  133. return new BackupData(table, column, primaryKey, autoIncrement, sqlType);
  134. }
  135. static BackupData of(BackupData data, SqlType sqlType) {
  136. return of(data.table, data.column, sqlType, data.primaryKey, data.autoIncrement);
  137. }
  138. }
  139. private static final class SqlType {
  140. public final int type;
  141. public final Integer precision;
  142. public final Integer scale;
  143. public SqlType(int type, Integer precision, Integer scale) {
  144. this.type = type;
  145. this.precision = precision;
  146. this.scale = scale;
  147. }
  148. static SqlType of(int type) {
  149. return of(type, null);
  150. }
  151. private static SqlType of(int type, Integer precision) {
  152. return of(type, precision, null);
  153. }
  154. private static SqlType of(int type, Integer precision, Integer scale) {
  155. return new SqlType(type, precision, scale);
  156. }
  157. }
  158. protected static final BackupData AUTHORSHIP_AUTHOR_ID = BackupData.of("AO_000000_AUTHORSHIP", "AUTHOR_ID", SqlType.of(Types.INTEGER));
  159. protected static final BackupData AUTHORSHIP_BOOK_ID = BackupData.of("AO_000000_AUTHORSHIP", "BOOK_ID", SqlType.of(Types.BIGINT));
  160. protected static final BackupData AUTHORSHIP_ID = BackupData.of("AO_000000_AUTHORSHIP", "ID", SqlType.of(Types.INTEGER), true, true);
  161. protected static final BackupData BOOK_ABSTRACT = BackupData.of("AO_000000_BOOK", "ABSTRACT", SqlType.of(Types.LONGVARCHAR));
  162. protected static final BackupData BOOK_ISBN = BackupData.of("AO_000000_BOOK", "ISBN", SqlType.of(Types.BIGINT), true, false);
  163. protected static final BackupData BOOK_READ = BackupData.of("AO_000000_BOOK", "IS_READ", SqlType.of(Types.BOOLEAN));
  164. protected static final BackupData BOOK_PAGES = BackupData.of("AO_000000_BOOK", "NUMBER_OF_PAGES", SqlType.of(Types.INTEGER));
  165. protected static final BackupData BOOK_PRICE = BackupData.of("AO_000000_BOOK", "PRICE", SqlType.of(Types.DOUBLE));
  166. protected static final BackupData BOOK_PUBLISHED = BackupData.of("AO_000000_BOOK", "PUBLISHED", SqlType.of(Types.TIMESTAMP));
  167. protected static final BackupData BOOK_TITLE = BackupData.of("AO_000000_BOOK", "TITLE", SqlType.of(Types.VARCHAR, 255));
  168. protected static final BackupData AUTHOR_NAME = BackupData.of("AO_000000_LONG_NAME_TO_AUTHOR", "NAME", SqlType.of(Types.VARCHAR, 60));
  169. protected static final BackupData AUTHOR_ID = BackupData.of("AO_000000_LONG_NAME_TO_AUTHOR", "ID", SqlType.of(Types.INTEGER), true, true);
  170. protected static Iterable<BackupData> H2_DATA = ImmutableList.of(
  171. AUTHORSHIP_AUTHOR_ID,
  172. AUTHORSHIP_BOOK_ID,
  173. AUTHORSHIP_ID,
  174. BackupData.of(BOOK_ABSTRACT, SqlType.of(Types.CLOB)),
  175. BOOK_ISBN,
  176. BOOK_READ,
  177. BOOK_PAGES,
  178. BOOK_PRICE,
  179. BOOK_PUBLISHED,
  180. BOOK_TITLE,
  181. AUTHOR_NAME,
  182. AUTHOR_ID
  183. );
  184. protected static Iterable<BackupData> HSQL_DATA = ImmutableList.of(
  185. AUTHORSHIP_AUTHOR_ID,
  186. AUTHORSHIP_BOOK_ID,
  187. AUTHORSHIP_ID,
  188. BOOK_ABSTRACT,
  189. BOOK_ISBN,
  190. BOOK_READ,
  191. BOOK_PAGES,
  192. BOOK_PRICE,
  193. BOOK_PUBLISHED,
  194. BOOK_TITLE,
  195. AUTHOR_NAME,
  196. AUTHOR_ID
  197. );
  198. protected static Iterable<BackupData> MYSQL_DATA = ImmutableList.of(
  199. AUTHORSHIP_AUTHOR_ID,
  200. AUTHORSHIP_BOOK_ID,
  201. AUTHORSHIP_ID,
  202. BackupData.of(BOOK_ABSTRACT, SqlType.of(Types.LONGVARCHAR)),
  203. BOOK_ISBN,
  204. BackupData.of(BOOK_READ, SqlType.of(Types.BIT)),
  205. BOOK_PAGES,
  206. BOOK_PRICE,
  207. BOOK_PUBLISHED,
  208. BOOK_TITLE,
  209. AUTHOR_NAME,
  210. AUTHOR_ID
  211. );
  212. protected static Iterable<BackupData> POSTGRES_DATA = ImmutableList.of(
  213. AUTHORSHIP_AUTHOR_ID,
  214. AUTHORSHIP_BOOK_ID,
  215. AUTHORSHIP_ID,
  216. BackupData.of(BOOK_ABSTRACT, SqlType.of(Types.VARCHAR)),
  217. BOOK_ISBN,
  218. BackupData.of(BOOK_READ, SqlType.of(Types.BIT)),
  219. BOOK_PAGES,
  220. BOOK_PRICE,
  221. BOOK_PUBLISHED,
  222. BOOK_TITLE,
  223. AUTHOR_NAME,
  224. AUTHOR_ID
  225. );
  226. protected static Iterable<BackupData> ORACLE_DATA = ImmutableList.of(
  227. BackupData.of(AUTHORSHIP_AUTHOR_ID, SqlType.of(Types.NUMERIC, 11)),
  228. BackupData.of(AUTHORSHIP_BOOK_ID, SqlType.of(Types.NUMERIC, 20)),
  229. BackupData.of(AUTHORSHIP_ID, SqlType.of(Types.NUMERIC, 11)),
  230. BackupData.of(BOOK_ABSTRACT, SqlType.of(Types.CLOB)),
  231. BackupData.of(BOOK_ISBN, SqlType.of(Types.NUMERIC, 20)),
  232. BackupData.of(BOOK_READ, SqlType.of(Types.NUMERIC, 1)),
  233. BackupData.of(BOOK_PAGES, SqlType.of(Types.NUMERIC, 11)),
  234. BackupData.of(BOOK_PRICE, SqlType.of(Types.NUMERIC, 126)),
  235. BOOK_PUBLISHED,
  236. BOOK_TITLE,
  237. AUTHOR_NAME,
  238. BackupData.of(AUTHOR_ID, SqlType.of(Types.NUMERIC, 11))
  239. );
  240. protected static Iterable<BackupData> LEGACY_ORACLE_DATA = ImmutableList.of(
  241. BackupData.of(AUTHORSHIP_AUTHOR_ID, SqlType.of(Types.NUMERIC, 11)),
  242. BackupData.of(AUTHORSHIP_BOOK_ID, SqlType.of(Types.NUMERIC, 20)),
  243. BackupData.of(AUTHORSHIP_ID, SqlType.of(Types.NUMERIC, 11)),
  244. BackupData.of(BOOK_ABSTRACT, SqlType.of(Types.CLOB)),
  245. BackupData.of(BOOK_ISBN, SqlType.of(Types.NUMERIC, 20)),
  246. BackupData.of(BOOK_READ, SqlType.of(Types.NUMERIC, 1)),
  247. BackupData.of(BOOK_PAGES, SqlType.of(Types.NUMERIC, 11)),
  248. BackupData.of(BOOK_PRICE, SqlType.of(Types.NUMERIC, 32, 16)),
  249. BOOK_PUBLISHED,
  250. BOOK_TITLE,
  251. AUTHOR_NAME,
  252. BackupData.of(AUTHOR_ID, SqlType.of(Types.NUMERIC, 11))
  253. );
  254. protected static Iterable<BackupData> SQL_SERVER_DATA_JTDS = ImmutableList.of(
  255. AUTHORSHIP_AUTHOR_ID,
  256. AUTHORSHIP_BOOK_ID,
  257. AUTHORSHIP_ID,
  258. BackupData.of(BOOK_ABSTRACT, SqlType.of(Types.CLOB)),
  259. BOOK_ISBN,
  260. BackupData.of(BOOK_READ, SqlType.of(Types.BIT)),
  261. BOOK_PAGES,
  262. BOOK_PRICE,
  263. BOOK_PUBLISHED,
  264. BOOK_TITLE,
  265. AUTHOR_NAME,
  266. AUTHOR_ID
  267. );
  268. protected static Iterable<BackupData> SQL_SERVER_DATA_MSJDBC = ImmutableList.of(
  269. AUTHORSHIP_AUTHOR_ID,
  270. AUTHORSHIP_BOOK_ID,
  271. AUTHORSHIP_ID,
  272. BackupData.of(BOOK_ABSTRACT, SqlType.of(Types.NVARCHAR)),
  273. BOOK_ISBN,
  274. BackupData.of(BOOK_READ, SqlType.of(Types.BIT)),
  275. BOOK_PAGES,
  276. BOOK_PRICE,
  277. BOOK_PUBLISHED,
  278. BOOK_TITLE,
  279. AUTHOR_NAME,
  280. AUTHOR_ID
  281. );
  282. }