package net.joelinn.quartz;
import net.joelinn.quartz.jobstore.RedisJobStore;
import net.joelinn.quartz.jobstore.RedisJobStoreSchema;
import org.junit.After;
import org.junit.Before;
import org.quartz.Calendar;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.calendar.WeeklyCalendar;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.quartz.spi.SchedulerSignaler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Protocol;
import redis.clients.util.Pool;
import redis.embedded.RedisServer;
import java.io.IOException;
import java.util.*;
import static net.joelinn.quartz.TestUtils.getPort;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.collection.IsMapContaining.hasKey;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
/**
* Joe Linn
* 7/15/2014
*/
public abstract class BaseTest {
private static final Logger logger = LoggerFactory.getLogger(BaseTest.class);
protected RedisServer redisServer;
protected Pool<Jedis> jedisPool;
protected RedisJobStore jobStore;
protected RedisJobStoreSchema schema;
protected Jedis jedis;
protected SchedulerSignaler mockScheduleSignaler;
protected int port;
protected String host = "localhost";
@Before
public void setUpRedis() throws IOException, SchedulerConfigException {
port = getPort();
logger.debug("Attempting to start embedded Redis server on port " + port);
redisServer = RedisServer.builder()
.port(port)
.build();
redisServer.start();
final short database = 1;
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setTestOnBorrow(true);
jedisPool = new JedisPool(jedisPoolConfig, host, port, Protocol.DEFAULT_TIMEOUT, null, database);
jobStore = new RedisJobStore();
jobStore.setHost(host);
jobStore.setLockTimeout(2000);
jobStore.setPort(port);
jobStore.setInstanceId("testJobStore1");
jobStore.setDatabase(database);
mockScheduleSignaler = mock(SchedulerSignaler.class);
jobStore.initialize(null, mockScheduleSignaler);
schema = new RedisJobStoreSchema();
jedis = jedisPool.getResource();
jedis.flushDB();
}
@After
public void tearDownRedis() throws InterruptedException {
jedis.close();
jedisPool.destroy();
redisServer.stop();
}
protected JobDetail getJobDetail(){
return getJobDetail("testJob", "testGroup");
}
protected JobDetail getJobDetail(final String name, final String group){
return JobBuilder.newJob(TestJob.class)
.withIdentity(name, group)
.usingJobData("timeout", 42)
.withDescription("I am describing a job!")
.build();
}
protected CronTriggerImpl getCronTrigger(){
String cron = "0/5 * * * * ?";
return (CronTriggerImpl) TriggerBuilder.newTrigger()
.forJob("testJob", "testGroup")
.withIdentity("testTrigger", "testTriggerGroup")
.withSchedule(CronScheduleBuilder.cronSchedule(cron))
.usingJobData("timeout", 5)
.withDescription("A description!")
.build();
}
protected CronTriggerImpl getCronTrigger(final String name, final String group, final JobKey jobKey){
return getCronTrigger(name, group, jobKey, "0 * * * * ?");
}
protected CronTriggerImpl getCronTrigger(final String name, final String group, final JobKey jobKey, String cron){
CronTriggerImpl trigger = (CronTriggerImpl) TriggerBuilder.newTrigger()
.forJob(jobKey)
.withIdentity(name, group)
.withSchedule(CronScheduleBuilder.cronSchedule(cron))
.usingJobData("timeout", 5)
.withDescription("A description!")
.build();
WeeklyCalendar calendar = new WeeklyCalendar();
calendar.setDaysExcluded(new boolean[]{false, false, false, false, false, false, false, false, false});
trigger.computeFirstFireTime(calendar);
trigger.setCalendarName("testCalendar");
return trigger;
}
protected Calendar getCalendar(){
WeeklyCalendar calendar = new WeeklyCalendar();
// exclude weekends
calendar.setDayExcluded(1, true);
calendar.setDayExcluded(7, true);
calendar.setDescription("Only run on weekdays.");
return calendar;
}
protected Map<JobDetail, Set<? extends Trigger>> getJobsAndTriggers(int jobGroups, int jobsPerGroup, int triggerGroupsPerJob, int triggersPerGroup){
return getJobsAndTriggers(jobGroups, jobsPerGroup, triggerGroupsPerJob, triggersPerGroup, "0 * * * * ?");
}
protected Map<JobDetail, Set<? extends Trigger>> getJobsAndTriggers(int jobGroups, int jobsPerGroup, int triggerGroupsPerJob, int triggersPerGroup, String cron){
Map<JobDetail, Set<? extends Trigger>> jobsAndTriggers = new HashMap<>();
for(int jobGroup = 0; jobGroup < jobGroups; jobGroup++){
String jobGroupName = String.format("jobGroup%s", jobGroup);
for(int job = 0; job < jobsPerGroup; job++){
String jobName = String.format("%sjob%s", jobGroupName, job);
JobDetail jobDetail = getJobDetail(jobName, jobGroupName);
Set<Trigger> triggerSet = new HashSet<>();
for(int triggerGroup = 0; triggerGroup < triggerGroupsPerJob; triggerGroup++){
String triggerGroupName = String.format("%striggerGroup%s", jobName, triggerGroup);
for(int trigger = 0; trigger < triggersPerGroup; trigger++){
String triggerName = String.format("%strigger%s", triggerGroupName, trigger);
triggerSet.add(getCronTrigger(triggerName, triggerGroupName, jobDetail.getKey(), cron));
}
}
jobsAndTriggers.put(jobDetail, triggerSet);
}
}
return jobsAndTriggers;
}
protected void storeJobAndTriggers(JobDetail job, Trigger... triggers) throws JobPersistenceException {
Set<Trigger> triggersSet = new HashSet<>(triggers.length);
Collections.addAll(triggersSet, triggers);
Map<JobDetail, Set<? extends Trigger>> jobsAndTriggers = new HashMap<>();
jobsAndTriggers.put(job, triggersSet);
jobStore.storeJobsAndTriggers(jobsAndTriggers, false);
}
protected void testJobStore(Properties quartzProperties) throws SchedulerException {
StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
schedulerFactory.initialize(quartzProperties);
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.start();
JobDetail job = getJobDetail("testJob1", "testJobGroup1");
CronTriggerImpl trigger = getCronTrigger("testTrigger1", "testTriggerGroup1", job.getKey(), "0/5 * * * * ?");
scheduler.scheduleJob(job, trigger);
JobDetail retrievedJob = jobStore.retrieveJob(job.getKey());
assertThat(retrievedJob, not(nullValue()));
assertThat(retrievedJob.getJobDataMap(), hasKey("timeout"));
CronTriggerImpl retrievedTrigger = (CronTriggerImpl) jobStore.retrieveTrigger(trigger.getKey());
assertThat(retrievedTrigger, not(nullValue()));
assertEquals(trigger.getCronExpression(), retrievedTrigger.getCronExpression());
scheduler.deleteJob(job.getKey());
assertThat(jobStore.retrieveJob(job.getKey()), nullValue());
assertThat(jobStore.retrieveTrigger(trigger.getKey()), nullValue());
scheduler.shutdown();
}
}