/**
* 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.File;
import java.io.PrintStream;
import java.util.List;
import java.util.Properties;
import javax.mail.Folder;
import javax.mail.Session;
import javax.mail.Store;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.PropertyConfigurator;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
import com.enioka.jqm.api.JobInstance;
import com.enioka.jqm.api.JobRequest;
import com.enioka.jqm.api.JqmClientFactory;
import com.enioka.jqm.api.Query;
import com.enioka.jqm.model.DeploymentParameter;
import com.enioka.jqm.model.JobDef;
import com.enioka.jqm.model.Queue;
import com.enioka.jqm.model.RRole;
import com.enioka.jqm.model.RUser;
import com.enioka.jqm.model.JobDef.PathType;
import com.enioka.jqm.test.helpers.CreationTools;
import com.enioka.jqm.test.helpers.TestHelpers;
public class MiscTest extends JqmBaseTest
{
@Test
public void testEmail() throws Exception
{
// Do not run in Eclipse, as it does not support the SMTP Maven plugin.
Assume.assumeTrue(!System.getProperty("java.class.path").contains("eclipse"));
CreationTools.createJobDef(null, true, "App", null, "jqm-tests/jqm-test-datetimemaven/target/test.jar", TestHelpers.qVip, 42,
"MarsuApplication", null, "Franquin", "ModuleMachin", "other", "other", true, cnx);
JobRequest.create("MarsuApplication", "TestUser").setEmail("test@jqm.com").submit();
addAndStartEngine();
TestHelpers.waitFor(1, 20000, cnx); // Need time for async mail sending.
Assert.assertEquals(1, TestHelpers.getOkCount(cnx));
Assert.assertEquals(0, TestHelpers.getNonOkCount(cnx));
Properties props = new Properties();
props.setProperty("mail.store.protocol", "imap");
int nbMail = 0;
try
{
Session session = Session.getInstance(props, null);
Store store = session.getStore();
store.connect("localhost", 10143, "testlogin", "testpassword");
Folder inbox = store.getFolder("INBOX");
nbMail = inbox.getMessageCount();
}
catch (Exception mex)
{
mex.printStackTrace();
}
Assert.assertEquals(1, nbMail);
}
@Test
public void testLongName() throws Exception
{
CreationTools.createJobDef(null, true, "App", null, "jqm-tests/jqm-test-datetimemaven/target/test.jar", TestHelpers.qVip, 42,
"Marsu-Application-nnnnnnnn-nnnnnn-nnnnnnnnnn-nnNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNnn-nnnnnnnnn", null, "Franquin",
"ModuleMachin", "other", "other", true, cnx);
JobRequest j = new JobRequest("Marsu-Application-nnnnnnnn-nnnnnn-nnnnnnnnnn-nnNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNnn-nnnnnnnnn",
"TestUser");
JqmClientFactory.getClient().enqueue(j);
addAndStartEngine();
TestHelpers.waitFor(1, 10000, cnx);
Assert.assertEquals(1, TestHelpers.getOkCount(cnx));
Assert.assertEquals(0, TestHelpers.getNonOkCount(cnx));
}
@Test
public void testJobWithSystemExit() throws Exception
{
JqmSimpleTest.create(cnx, "pyl.SecExit", "jqm-test-pyl-nodep").expectOk(0).expectNonOk(1).run(this);
}
@Test
public void testJobWithPersistenceUnit() throws Exception
{
// The PU test expects an HSQLDB database which does not exist when running the tests on other databases
Assume.assumeTrue(JqmBaseTest.s != null);
CreationTools.createDatabaseProp("jdbc/test", "org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem:testdbmarsu", "SA", "", cnx,
"SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS", null);
CreationTools.createDatabaseProp("jdbc/jqm2", "org.hsqldb.jdbcDriver", "jdbc:hsqldb:hsql://localhost/testdbengine", "SA", "", cnx,
"SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS", null);
CreationTools.createJobDef(null, true, "App", null, "jqm-tests/jqm-test-em/target/test.jar", TestHelpers.qVip, 42, "jqm-test-em",
null, "Franquin", "ModuleMachin", "other", "other", false, cnx);
JobRequest.create("jqm-test-em", "TestUser").submit();
addAndStartEngine();
TestHelpers.waitFor(2, 10000, cnx);
Assert.assertEquals(2, TestHelpers.getOkCount(cnx));
}
@Test
public void testJobWithPersistenceUnitAndEngineApi() throws Exception
{
CreationTools.createDatabaseProp("jdbc/test", "org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem:testdbmarsu", "SA", "", cnx,
"SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS", null);
JqmSimpleTest.create(cnx, "pyl.CompatHibApi", "jqm-test-pyl-hibapi").expectOk(2).run(this);
}
@Test
public void testJobWithPersistenceUnitAndEngineApiAndXmlParams() throws Exception
{
CreationTools.createDatabaseProp("jdbc/test", "org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem:testdbmarsu", "SA", "", cnx,
"SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS", null);
CreationTools.createDatabaseProp("jdbc/jqm2", "org.hsqldb.jdbcDriver", "jdbc:hsqldb:hsql://localhost/testdbengine", "SA", "", cnx,
"SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS", null);
cnx.commit();
Main.main(new String[] { "-importjobdef", "target/payloads/jqm-test-xml/xmlstop.xml" });
JobRequest j = new JobRequest("CompatHibApi", "TestUser");
JqmClientFactory.getClient().enqueue(j);
addAndStartEngine();
TestHelpers.waitFor(1, 10000, cnx);
Assert.assertEquals(1, TestHelpers.getOkCount(cnx));
}
@Test
public void testRemoteStop() throws Exception
{
Helpers.setSingleParam("internalPollingPeriodMs", "10", cnx);
addAndStartEngine();
cnx.runUpdate("node_update_stop_by_id", TestHelpers.node.getId());
cnx.commit();
TestHelpers.waitFor(2, 3000, cnx);
Assert.assertFalse(engines.get("localhost").isAllPollersPolling());
engines.clear();
}
@Test
public void testNoDoubleStart() throws Exception
{
Helpers.setSingleParam("internalPollingPeriodMs", "500", cnx);
Helpers.setSingleParam("disableVerboseStartup", "false", cnx);
JqmEngine engine1 = new JqmEngine();
engine1.start("localhost");
JqmEngine engine2 = new JqmEngine();
try
{
engine2.start("localhost");
Assert.fail("engine should not have been able to start");
}
catch (JqmInitErrorTooSoon e)
{
jqmlogger.info(e);
}
finally
{
engine1.stop();
}
}
@Test
public void testStartupCleanupRunning() throws Exception
{
CreationTools.createJobDef(null, true, "App", null, "jqm-tests/jqm-test-em/target/test.jar", TestHelpers.qVip, 42, "jqm-test-em",
null, "Franquin", "ModuleMachin", "other", "other", false, cnx);
/// Create a running job that should be cleaned at startup
int i1 = JqmClientFactory.getClient().enqueue("jqm-test-em", "test");
cnx.runUpdate("ji_update_poll", TestHelpers.node.getId(), TestHelpers.qVip, 10);
cnx.runUpdate("jj_update_run_by_id", i1);
cnx.commit();
addAndStartEngine();
Assert.assertEquals(0, TestHelpers.getQueueAllCount(cnx));
Assert.assertEquals(1, TestHelpers.getHistoryAllCount(cnx));
Assert.assertEquals(1, TestHelpers.getNonOkCount(cnx));
}
@Test
public void testStartupCleanupAttr() throws Exception
{
CreationTools.createJobDef(null, true, "App", null, "jqm-tests/jqm-test-em/target/test.jar", TestHelpers.qVip, 42, "jqm-test-em",
null, "Franquin", "ModuleMachin", "other", "other", false, cnx);
// Create a running job that should be cleaned at startup
JqmClientFactory.getClient().enqueue("jqm-test-em", "test");
cnx.runUpdate("ji_update_poll", TestHelpers.node.getId(), TestHelpers.qVip, 10);
cnx.commit();
addAndStartEngine();
Assert.assertEquals(0, TestHelpers.getQueueAllCount(cnx));
Assert.assertEquals(1, TestHelpers.getHistoryAllCount(cnx));
Assert.assertEquals(1, TestHelpers.getNonOkCount(cnx));
}
@Test
public void testQuery() throws Exception
{
CreationTools.createJobDef(null, true, "pyl.KillMe", null, "jqm-tests/jqm-test-pyl/target/test.jar", TestHelpers.qNormal, 42,
"jqm-test-kill", null, "Franquin", "ModuleMachin", "other", "other", false, cnx);
cnx.commit();
JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
jqmlogger.debug("COUNT RUNNING " + cnx.runSelectSingle("ji_select_count_running", Integer.class));
jqmlogger.debug("COUNT ALL " + cnx.runSelectSingle("ji_select_count_all", Integer.class));
Assert.assertEquals(0, Query.create().setQueryLiveInstances(true).setQueryHistoryInstances(false)
.addStatusFilter(com.enioka.jqm.api.State.RUNNING).addStatusFilter(com.enioka.jqm.api.State.ENDED).run().size());
Assert.assertEquals(5, Query.create().setQueryLiveInstances(true).setQueryHistoryInstances(false)
.addStatusFilter(com.enioka.jqm.api.State.SUBMITTED).run().size());
}
@Test
public void testQueueWidth() throws Exception
{
// Only 3 threads
int qId = Queue.create(cnx, "testqueue", "", false);
DeploymentParameter.create(cnx, TestHelpers.node.getId(), 3, 1, qId);
CreationTools.createJobDef(null, true, "pyl.KillMe", null, "jqm-tests/jqm-test-pyl/target/test.jar", qId, 42, "jqm-test-kill", null,
"Franquin", "ModuleMachin", "other", "other", false, cnx);
cnx.commit();
int i1 = JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
int i2 = JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
int i3 = JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
int i4 = JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
int i5 = JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
addAndStartEngine();
// Scenario is: 5 jobs in queue. 3 should run. 2 are then killed - 3 should still run.
Thread.sleep(3000);
jqmlogger.debug("COUNT RUNNING " + cnx.runSelectSingle("ji_select_count_running", Integer.class));
jqmlogger.debug("COUNT ALL " + cnx.runSelectSingle("ji_select_count_all", Integer.class));
Assert.assertEquals(3, Query.create().setQueryLiveInstances(true).setQueryHistoryInstances(false)
.addStatusFilter(com.enioka.jqm.api.State.RUNNING).run().size());
Assert.assertEquals(2, Query.create().setQueryLiveInstances(true).setQueryHistoryInstances(false)
.addStatusFilter(com.enioka.jqm.api.State.SUBMITTED).run().size());
JqmClientFactory.getClient().killJob(i1);
JqmClientFactory.getClient().killJob(i2);
Thread.sleep(2000);
Assert.assertEquals(3, Query.create().setQueryLiveInstances(true).setQueryHistoryInstances(false)
.addStatusFilter(com.enioka.jqm.api.State.RUNNING).run().size());
Assert.assertEquals(0, Query.create().setQueryLiveInstances(true).setQueryHistoryInstances(false)
.addStatusFilter(com.enioka.jqm.api.State.SUBMITTED).run().size());
JqmClientFactory.getClient().killJob(i3);
JqmClientFactory.getClient().killJob(i4);
JqmClientFactory.getClient().killJob(i5);
TestHelpers.waitFor(5, 10000, cnx);
}
// Does the poller take multiple JI on each loop?
@Test
public void testQueuePollWidth() throws Exception
{
// Only 3 threads, one poll every hour
int qId = Queue.create(cnx, "testqueue", "", false);
DeploymentParameter.create(cnx, TestHelpers.node.getId(), 3, 3600000, qId);
CreationTools.createJobDef(null, true, "pyl.KillMe", null, "jqm-tests/jqm-test-pyl/target/test.jar", qId, 42, "jqm-test-kill", null,
"Franquin", "ModuleMachin", "other", "other", false, cnx);
JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
JqmClientFactory.getClient().enqueue("jqm-test-kill", "test");
// Scenario is: 5 jobs in queue with 3 slots. 3 jobs should run. 2 are then killed - 3 should still run.
// (bc: poller loops on job end).
addAndStartEngine();
TestHelpers.waitForRunning(3, 3000, cnx);
// Check 3 running (max queue size).
Assert.assertEquals(3, Query.create().setQueryLiveInstances(true).setQueryHistoryInstances(false)
.addStatusFilter(com.enioka.jqm.api.State.RUNNING).run().size());
Assert.assertEquals(2, Query.create().setQueryLiveInstances(true).setQueryHistoryInstances(false)
.addStatusFilter(com.enioka.jqm.api.State.SUBMITTED).run().size());
// Kill 2.
List<JobInstance> running = Query.create().setQueryLiveInstances(true).setQueryHistoryInstances(false)
.addStatusFilter(com.enioka.jqm.api.State.RUNNING).run();
JqmClientFactory.getClient().killJob(running.get(0).getId());
JqmClientFactory.getClient().killJob(running.get(1).getId());
TestHelpers.waitFor(2, 10000, cnx);
TestHelpers.waitForRunning(3, 10000, cnx);
// Check the two waiting jobs have started.
Assert.assertEquals(3, Query.create().setQueryLiveInstances(true).setQueryHistoryInstances(false)
.addStatusFilter(com.enioka.jqm.api.State.RUNNING).run().size());
Assert.assertEquals(0, Query.create().setQueryLiveInstances(true).setQueryHistoryInstances(false)
.addStatusFilter(com.enioka.jqm.api.State.SUBMITTED).run().size());
// Kill remaining
running = Query.create().setQueryLiveInstances(true).setQueryHistoryInstances(false)
.addStatusFilter(com.enioka.jqm.api.State.RUNNING).run();
JqmClientFactory.getClient().killJob(running.get(0).getId());
JqmClientFactory.getClient().killJob(running.get(1).getId());
JqmClientFactory.getClient().killJob(running.get(2).getId());
// Check all jobs are killed (and not cancelled as they would have been if not started)).
TestHelpers.waitFor(5, 10000, cnx);
this.displayAllHistoryTable();
Assert.assertEquals(5, Query.create().addStatusFilter(com.enioka.jqm.api.State.KILLED).run().size());
}
@Test
public void testMultiLog() throws Exception
{
PrintStream out_ini = System.out;
PrintStream err_ini = System.err;
Helpers.setSingleParam("logFilePerLaunch", "true", cnx);
CreationTools.createJobDef(null, true, "App", null, "jqm-tests/jqm-test-datetimemaven/target/test.jar", TestHelpers.qVip, 42,
"MarsuApplication", null, "Franquin", "ModuleMachin", "other", "other", true, cnx);
int i = JobRequest.create("MarsuApplication", "TestUser").submit();
addAndStartEngine();
TestHelpers.waitFor(1, 20000, cnx);
String fileName = StringUtils.leftPad("" + i, 10, "0") + ".stdout.log";
File f = new File(FilenameUtils.concat(((MultiplexPrintStream) System.out).rootLogDir, fileName));
Assert.assertEquals(1, TestHelpers.getOkCount(cnx));
Assert.assertEquals(0, TestHelpers.getNonOkCount(cnx));
Assert.assertTrue(f.exists());
System.setErr(err_ini);
System.setOut(out_ini);
}
@Test
public void testSingleLauncher() throws Exception
{
CreationTools.createJobDef(null, true, "App", null, "jqm-tests/jqm-test-datetimemaven/target/test.jar", TestHelpers.qVip, 42,
"MarsuApplication", null, "Franquin", "ModuleMachin", "other", "other", true, cnx);
int i = JobRequest.create("MarsuApplication", "TestUser").submit();
cnx.runUpdate("ji_update_poll", TestHelpers.node.getId(), TestHelpers.qVip, 10);
cnx.runUpdate("debug_jj_update_node_by_id", TestHelpers.node.getId(), i);
cnx.commit();
Main.main(new String[] { "-s", String.valueOf(i) });
// This is not really a one shot JVM, so let's reset log4j
LogManager.resetConfiguration();
PropertyConfigurator.configure("target/classes/log4j.properties");
Assert.assertEquals(1, TestHelpers.getOkCount(cnx));
Assert.assertEquals(0, TestHelpers.getNonOkCount(cnx));
}
@Test
public void testExternalLaunch() throws Exception
{
int jdId = CreationTools.createJobDef(null, true, "App", null, "jqm-tests/jqm-test-datetimemaven/target/test.jar", TestHelpers.qVip,
42, "MarsuApplication", null, "Franquin", "ModuleMachin", "other", "other", true, cnx);
JobDef.setExternal(cnx, jdId);
cnx.commit();
JobRequest.create("MarsuApplication", "TestUser").submit();
addAndStartEngine();
TestHelpers.waitFor(1, 20000, cnx);
Assert.assertEquals(1, TestHelpers.getOkCount(cnx));
Assert.assertEquals(0, TestHelpers.getNonOkCount(cnx));
}
@Test
public void testExternalKill() throws Exception
{
Helpers.setSingleParam("internalPollingPeriodMs", "100", cnx);
int i = JqmSimpleTest.create(cnx, "pyl.KillMeNot").setExternal().addWaitTime(3000).expectNonOk(0).expectOk(0).run(this);
JqmClientFactory.getClient().killJob(i);
TestHelpers.waitFor(1, 20000, cnx);
Assert.assertEquals(0, TestHelpers.getOkCount(cnx));
Assert.assertEquals(1, TestHelpers.getNonOkCount(cnx));
}
@Test
public void testCliChangeUser()
{
Helpers.updateConfiguration(cnx);
Main.main(new String[] { "-U", "myuser", "mypassword", "administrator", "client" });
RUser u = RUser.selectlogin(cnx, "myuser");
Assert.assertEquals(2, u.getRoles(cnx).size());
boolean admin = false, client = false;
for (RRole r : u.getRoles(cnx))
{
if (r.getName().equals("administrator"))
{
admin = true;
}
if (r.getName().equals("client"))
{
client = true;
}
}
Assert.assertTrue(client && admin);
Main.main(new String[] { "-U", "myuser", "mypassword", "administrator" });
Assert.assertEquals(1, u.getRoles(cnx).size());
Main.main(new String[] { "-U", "myuser,mypassword,administrator,config admin" });
Assert.assertEquals(2, u.getRoles(cnx).size());
}
@Test
public void testMavenArtifact()
{
CreationTools.createJobDef(null, true, "pyl.Nothing", null, "com.enioka.jqm:jqm-test-pyl-nodep:1.3.2", TestHelpers.qVip, 42,
"jqm-test-maven", null, "Franquin", "ModuleMachin", "other", "other", false, cnx, null, false, null, false, PathType.MAVEN);
JobRequest.create("jqm-test-maven", null).submit();
addAndStartEngine();
TestHelpers.waitFor(1, 10000, cnx);
Assert.assertEquals(1, TestHelpers.getOkCount(cnx));
Assert.assertEquals(0, TestHelpers.getNonOkCount(cnx));
}
}