/**
* Copyright © 2013 enioka. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.enioka.jqm.tools;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.naming.NamingException;
import javax.naming.spi.NamingManager;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.hsqldb.Server;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.rules.TestName;
import com.enioka.jqm.api.JobInstance;
import com.enioka.jqm.api.JqmClientFactory;
import com.enioka.jqm.api.Query;
import com.enioka.jqm.jdbc.Db;
import com.enioka.jqm.jdbc.DbConn;
import com.enioka.jqm.test.helpers.TestHelpers;
public class JqmBaseTest
{
public static Logger jqmlogger = Logger.getLogger(JqmBaseTest.class);
public static Server s;
protected static Db db;
public Map<String, JqmEngine> engines = new HashMap<String, JqmEngine>();
public List<DbConn> cnxs = new ArrayList<DbConn>();
protected DbConn cnx;
@Rule
public TestName testName = new TestName();
@BeforeClass
public static void testInit() throws Exception
{
if (db == null)
{
JndiContext.createJndiContext();
// If needed, create an HSQLDB server.
InputStream fis = null;
Properties p = new Properties();
fis = Helpers.class.getClassLoader().getResourceAsStream("jqm.properties");
if (fis != null)
{
p.load(fis);
IOUtils.closeQuietly(fis);
fis.close();
}
if (p.isEmpty() || !p.containsKey("com.enioka.jqm.jdbc.datasource") || (p.containsKey("com.enioka.jqm.jdbc.datasource")
&& p.getProperty("com.enioka.jqm.jdbc.datasource").contains("hsql")))
{
s = new Server();
s.setDatabaseName(0, "testdbengine");
s.setDatabasePath(0, "mem:testdbengine");
s.setLogWriter(null);
s.setSilent(true);
s.start();
}
// In all cases load the datasource. (the helper itself will load the property file if any).
db = Helpers.getDb();
}
}
@Before
public void beforeTest()
{
jqmlogger.debug("**********************************************************");
jqmlogger.debug("Starting test " + testName.getMethodName());
try
{
((JndiContext) NamingManager.getInitialContext(null)).resetSingletons();
}
catch (NamingException e)
{
jqmlogger.warn("Could not purge test JNDI context", e);
}
JqmClientFactory.resetClient(null);
cnx = getNewDbSession();
TestHelpers.cleanup(cnx);
TestHelpers.createTestData(cnx);
cnx.commit();
}
@After
public void afterTest()
{
jqmlogger.debug("*** Cleaning after test " + testName.getMethodName());
for (String k : engines.keySet())
{
JqmEngine e = engines.get(k);
e.stop();
}
engines.clear();
for (DbConn em : cnxs)
{
em.close();
}
cnxs.clear();
// Java 6 GC being rather inefficient, we must run it multiple times to correctly collect Jetty-created class loaders and avoid
// permgen issues
System.runFinalization();
System.gc();
System.runFinalization();
System.gc();
System.gc();
}
protected JqmEngine addAndStartEngine()
{
return addAndStartEngine("localhost");
}
protected JqmEngine addAndStartEngine(String nodeName)
{
JqmEngine e = new JqmEngine();
engines.put(nodeName, e);
e.start(nodeName);
return e;
}
protected void stopAndRemoveEngine(String nodeName)
{
JqmEngine e = engines.get(nodeName);
e.stop();
engines.remove(nodeName);
}
protected DbConn getNewDbSession()
{
DbConn cnx = db.getConn();
cnxs.add(cnx);
return cnx;
}
protected void sleep(int s)
{
this.sleepms(1000 * s);
}
protected void sleepms(int ms)
{
try
{
Thread.sleep(ms);
}
catch (InterruptedException e)
{
// not an issue in tests
}
}
protected void waitDbStop()
{
while (s.getState() != 16)
{
this.sleepms(1);
}
}
protected void simulateDbFailure()
{
if (db.getProduct().contains("hsql"))
{
jqmlogger.info("DB is going down");
s.stop();
this.waitDbStop();
jqmlogger.info("DB is now fully down");
this.sleep(1);
jqmlogger.info("Restarting DB");
s.start();
}
else if (db.getProduct().contains("postgresql"))
{
try
{
// update pg_database set datallowconn = false where datname = 'jqm' // Cannot run, as we cannot reconnect afterward!
cnx.runRawSelect("select pg_terminate_backend(pid) from pg_stat_activity where datname='jqm';");
}
catch (Exception e)
{
// Do nothing - the query is a suicide so it cannot work fully.
}
Helpers.closeQuietly(cnx);
cnx = getNewDbSession();
}
}
protected void displayAllHistoryTable()
{
java.text.SimpleDateFormat format = new java.text.SimpleDateFormat("HH:mm:ss.SSS");
jqmlogger.debug("==========================================================================================");
for (JobInstance h : Query.create().run())
{
jqmlogger.debug("JobInstance Id: " + h.getId() + " | " + h.getState() + " | JD: " + h.getApplicationName() + " | "
+ h.getQueueName() + " | enqueue: " + format.format(h.getEnqueueDate().getTime()) + " | exec: "
+ (h.getBeganRunningDate() != null ? format.format(h.getBeganRunningDate().getTime()) : null) + " | end: "
+ (h.getEndDate() != null ? format.format(h.getEndDate().getTime()) : null));
}
jqmlogger.debug("==========================================================================================");
}
}