1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.jumpmind.symmetric.test;
21
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.InputStreamReader;
27 import java.net.URL;
28 import java.sql.Connection;
29 import java.sql.DriverManager;
30 import java.sql.SQLException;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collection;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Properties;
37 import java.util.Set;
38
39 import javax.servlet.ServletContext;
40 import javax.sql.DataSource;
41
42 import org.apache.commons.lang.StringUtils;
43 import org.apache.commons.logging.Log;
44 import org.apache.commons.logging.LogFactory;
45 import org.apache.ddlutils.Platform;
46 import org.apache.ddlutils.io.DatabaseIO;
47 import org.apache.ddlutils.model.Database;
48 import org.apache.derby.jdbc.EmbeddedDriver;
49 import org.jumpmind.symmetric.SymmetricEngine;
50 import org.jumpmind.symmetric.SymmetricWebServer;
51 import org.jumpmind.symmetric.common.Constants;
52 import org.jumpmind.symmetric.common.ParameterConstants;
53 import org.jumpmind.symmetric.db.IDbDialect;
54 import org.jumpmind.symmetric.db.SqlScript;
55 import org.jumpmind.symmetric.service.IBootstrapService;
56 import org.jumpmind.symmetric.util.AppUtils;
57 import org.junit.Assert;
58 import org.springframework.mock.web.MockHttpServletRequest;
59
60 public class TestSetupUtil {
61
62 static final Log logger = LogFactory.getLog(TestSetupUtil.class);
63
64 static private SymmetricEngine clientEngine;
65
66 static private SymmetricWebServer rootServer;
67
68 public static Collection<String[]> lookupDatabasePairs(String testPrefix) {
69 Properties properties = getTestProperties(testPrefix);
70 String[] clientDatabaseTypes = StringUtils.split(properties.getProperty(testPrefix + ".client"), ",");
71 String[] rootDatabaseTypes = getRootDbTypes(testPrefix);
72
73 String[][] clientAndRootCombos = new String[rootDatabaseTypes.length * clientDatabaseTypes.length][2];
74
75 int index = 0;
76 for (String rootDatabaseType : rootDatabaseTypes) {
77 for (String clientDatabaseType : clientDatabaseTypes) {
78 clientAndRootCombos[index][0] = clientDatabaseType;
79 clientAndRootCombos[index++][1] = rootDatabaseType;
80 }
81 }
82 return Arrays.asList(clientAndRootCombos);
83 }
84
85 public static Collection<String[]> lookupDatabases(String testPrefix) {
86 List<String[]> list = new ArrayList<String[]>();
87 String[] dbs = getRootDbTypes(testPrefix);
88 for (String string : dbs) {
89 list.add(new String[] { string });
90 }
91 return list;
92 }
93
94 public static void cleanup() throws Exception {
95 if (clientEngine != null) {
96 clientEngine.stop();
97 clientEngine = null;
98 }
99 if (rootServer != null) {
100 rootServer.stop();
101 rootServer = null;
102 }
103
104 closeDerbyAndReloadDriver();
105 }
106
107 /***
108 * Unit tests were failing after opening and closing several data connection pools against the
109 * same database in memory. After shutting down the connection pool, it seems to help by shutting
110 * down the entire database.
111 */
112 protected static void closeDerbyAndReloadDriver() throws SQLException {
113 try {
114 DriverManager.getConnection("jdbc:derby:;shutdown=true");
115 } catch (SQLException ex) {
116 if (ex.getErrorCode() == 50000) {
117 DriverManager.registerDriver(new EmbeddedDriver());
118 logger.info(ex.getMessage());
119 }
120 } catch (Exception ex) {
121
122 }
123 }
124
125 public static void setup(String testPrefix, String sqlScriptSuffix, String clientDb, String rootDb)
126 throws Exception {
127 if (rootDb != null) {
128 rootServer = new SymmetricWebServer(new SymmetricEngine("file:"
129 + writeTempPropertiesFileFor(testPrefix, rootDb, DatabaseRole.ROOT).getAbsolutePath()));
130 dropAndCreateDatabaseTables(rootDb, rootServer.getEngine());
131 IBootstrapService bootstrapService = AppUtils.find(Constants.BOOTSTRAP_SERVICE, rootServer.getEngine());
132 bootstrapService.setupDatabase();
133 new SqlScript(getResource("/" + testPrefix + sqlScriptSuffix), (DataSource) rootServer.getEngine()
134 .getApplicationContext().getBean(Constants.DATA_SOURCE), true).execute();
135 rootServer.setJoin(false);
136 rootServer.start(8888);
137 }
138
139 if (clientDb != null) {
140 clientEngine = new SymmetricEngine("file:"
141 + writeTempPropertiesFileFor(testPrefix, clientDb, DatabaseRole.CLIENT).getAbsolutePath(), null);
142 dropAndCreateDatabaseTables(clientDb, clientEngine);
143 }
144 }
145
146 public static SymmetricEngine getRootEngine() {
147 return rootServer.getEngine();
148 }
149
150 public static SymmetricEngine getClientEngine() {
151 return clientEngine;
152 }
153
154 public static boolean isConnectionValid(Properties properties) throws Exception {
155 try {
156 Class.forName(properties.getProperty("db.driver"));
157 Connection c = DriverManager.getConnection(properties.getProperty("db.url"), properties
158 .getProperty("db.user"), properties.getProperty("db.password"));
159 c.close();
160 return true;
161 } catch (Exception ex) {
162 logger.error("Could not connect to the test database using the url: " + properties.getProperty("db.url")
163 + " and classpath: " + System.getProperty("java.class.path"), ex);
164 return false;
165 }
166 }
167
168 protected static void dropAndCreateDatabaseTables(String databaseType, SymmetricEngine engine) {
169 DataSource ds = (DataSource) engine.getApplicationContext().getBean(Constants.DATA_SOURCE);
170 try {
171 IDbDialect dialect = (IDbDialect) engine.getApplicationContext().getBean(Constants.DB_DIALECT);
172 Platform platform = dialect.getPlatform();
173 Database testDb = getTestDatabase();
174 platform.dropTables(testDb, true);
175 dialect.purge();
176
177 new SqlScript(getResource(TestConstants.TEST_DROP_ALL_SCRIPT), ds, false).execute();
178
179 String fileName = TestConstants.TEST_DROP_SEQ_SCRIPT + databaseType + ".sql";
180 URL url = getResource(fileName);
181 if (url != null) {
182 new SqlScript(url, ds, false).execute();
183 }
184
185 platform.createTables(testDb, false, true);
186
187 } catch (Exception e) {
188 throw new RuntimeException(e);
189 }
190 }
191
192 protected static URL getResource(String resource) {
193 return TestSetupUtil.class.getResource(resource);
194 }
195
196 protected static Database getTestDatabase() throws IOException {
197 return new DatabaseIO().read(new InputStreamReader(getResource("/test-tables-ddl.xml").openStream()));
198 }
199
200 public static File writeTempPropertiesFileFor(String testPrefix, String databaseType, DatabaseRole databaseRole) {
201 try {
202 Properties properties = getTestProperties(testPrefix);
203 Properties newProperties = new Properties();
204 Set<Object> keys = properties.keySet();
205 for (Object string : keys) {
206 String key = (String) string;
207 String dbRoleReplaceToken = databaseType + "." + databaseRole.name().toLowerCase() + ".";
208 if (key.startsWith(dbRoleReplaceToken)) {
209 String newKey = key.substring(dbRoleReplaceToken.length());
210 newProperties.put(newKey, properties.get(key));
211 } else if (key.startsWith(databaseType)) {
212 String newKey = key.substring(databaseType.length() + 1);
213 newProperties.put(newKey, properties.get(key));
214 } else {
215 newProperties.put(key, properties.get(key));
216 }
217 }
218
219 if (isConnectionValid(newProperties)) {
220 newProperties.setProperty(ParameterConstants.NODE_GROUP_ID,
221 databaseRole == DatabaseRole.CLIENT ? TestConstants.TEST_CLIENT_NODE_GROUP
222 : TestConstants.TEST_ROOT_NODE_GROUP);
223 newProperties.setProperty(ParameterConstants.EXTERNAL_ID,
224 databaseRole == DatabaseRole.ROOT ? TestConstants.TEST_ROOT_EXTERNAL_ID
225 : TestConstants.TEST_CLIENT_EXTERNAL_ID);
226 newProperties.setProperty(ParameterConstants.MY_URL, "http://localhost:8888/sync");
227 newProperties.setProperty(ParameterConstants.REGISTRATION_URL,
228 databaseRole == DatabaseRole.CLIENT ? "http://localhost:8888/sync" : "");
229 newProperties.setProperty(ParameterConstants.ENGINE_NAME, databaseRole.name().toLowerCase());
230
231 File propertiesFile = File.createTempFile("symmetric-test.", ".properties");
232 FileOutputStream os = new FileOutputStream(propertiesFile);
233 newProperties.store(os, "generated by the symmetricds unit tests");
234 os.close();
235 propertiesFile.deleteOnExit();
236 return propertiesFile;
237
238 } else {
239 Assert.fail("Could not find a valid connection for " + databaseType);
240 return null;
241 }
242 } catch (RuntimeException ex) {
243 throw ex;
244 } catch (Exception ex) {
245 throw new RuntimeException(ex);
246 }
247
248 }
249
250 public static Properties getTestProperties(String testPrefix) {
251 try {
252 final String TEST_PROPERTIES_FILE = "/symmetric-" + testPrefix + ".properties";
253 Properties properties = new Properties();
254
255 properties.load(TestSetupUtil.class.getResourceAsStream(TEST_PROPERTIES_FILE));
256 String homeDir = System.getProperty("user.home");
257 File propertiesFile = new File(homeDir + TEST_PROPERTIES_FILE);
258 if (propertiesFile.exists()) {
259 FileInputStream f = new FileInputStream(propertiesFile);
260 properties.load(f);
261 f.close();
262 } else {
263 logger.info("Could not find " + propertiesFile.getAbsolutePath()
264 + ". Using all of the default properties");
265 }
266 return properties;
267 } catch (IOException ex) {
268 throw new RuntimeException(ex);
269 }
270 }
271
272 protected static String[] getRootDbTypes(String testPrefix) {
273 Properties properties = getTestProperties(testPrefix);
274 return StringUtils.split(properties.getProperty(testPrefix + ".root"), ",");
275 }
276
277 public static MockHttpServletRequest createMockHttpServletRequest(ServletContext servletContext, String method,
278 String uri, Map<String, String> parameters) {
279 final String[] uriParts = StringUtils.split(uri, "?");
280 final MockHttpServletRequest request = new MockHttpServletRequest(servletContext, method, uriParts[0]);
281 if (uriParts.length > 1) {
282 request.setQueryString(uriParts[1]);
283 }
284 if (parameters != null) {
285 request.setParameters(parameters);
286 }
287 return request;
288 }
289
290 }