package org.jooby.internal.quartz;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.isA;
import static org.junit.Assert.assertEquals;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import javax.inject.Provider;
import javax.sql.DataSource;
import org.jooby.test.MockUnit;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.quartz.CalendarIntervalTrigger;
import org.quartz.CronTrigger;
import org.quartz.DailyTimeIntervalTrigger;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.jdbcjobstore.JobStoreTX;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;
import org.quartz.utils.DBConnectionManager;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.name.Names;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import com.typesafe.config.ConfigValueFactory;
@RunWith(PowerMockRunner.class)
@PrepareForTest({QuartzProvider.class, StdSchedulerFactory.class, DBConnectionManager.class,
QuartzConnectionProvider.class })
public class QuartzProviderTest {
@SuppressWarnings({"unchecked", "rawtypes" })
@Test
public void defaultSetup() throws Exception {
Config conf = ConfigFactory.empty()
.withValue("org.quartz.jobStore.class", ConfigValueFactory.fromAnyRef("X"));
Properties props = new Properties();
props.setProperty("org.quartz.jobStore.class", "X");
new MockUnit(Injector.class, Scheduler.class, Map.class)
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
scheduler.setJobFactory(isA(JobFactory.class));
})
.expect(unit -> {
Map triggers = unit.get(Map.class);
expect(triggers.entrySet()).andReturn(Collections.emptySet());
})
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
StdSchedulerFactory factory = unit.mockConstructor(StdSchedulerFactory.class,
new Class[]{Properties.class }, props);
expect(factory.getScheduler()).andReturn(scheduler);
})
.run(unit -> {
new QuartzProvider(unit.get(Injector.class), conf, unit.get(Map.class));
});
}
@SuppressWarnings({"unchecked", "rawtypes" })
@Test
public void guiceJobFactory() throws Exception {
Config conf = ConfigFactory.empty()
.withValue("org.quartz.jobStore.class", ConfigValueFactory.fromAnyRef("X"));
Properties props = new Properties();
props.setProperty("org.quartz.jobStore.class", "X");
Job job = ctx -> {
};
new MockUnit(Injector.class, Scheduler.class, Map.class, TriggerFiredBundle.class)
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
scheduler.setJobFactory(unit.capture(JobFactory.class));
})
.expect(unit -> {
Map triggers = unit.get(Map.class);
expect(triggers.entrySet()).andReturn(Collections.emptySet());
})
.expect(unit -> {
Class jobClass = Job.class;
JobDetail jobDetail = unit.mock(JobDetail.class);
expect(jobDetail.getJobClass()).andReturn(jobClass);
TriggerFiredBundle bundle = unit.get(TriggerFiredBundle.class);
expect(bundle.getJobDetail()).andReturn(jobDetail);
Injector injector = unit.get(Injector.class);
expect(injector.getInstance(Job.class)).andReturn(job);
})
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
StdSchedulerFactory factory = unit.mockConstructor(StdSchedulerFactory.class,
new Class[]{Properties.class }, props);
expect(factory.getScheduler()).andReturn(scheduler);
})
.run(
unit -> {
new QuartzProvider(unit.get(Injector.class), conf, unit.get(Map.class));
},
unit -> {
JobFactory factory = unit.captured(JobFactory.class).iterator().next();
Job newJob = factory.newJob(unit.get(TriggerFiredBundle.class),
unit.get(Scheduler.class));
assertEquals(job, newJob);
});
}
@SuppressWarnings({"unchecked", "rawtypes" })
@Test
public void jdbcSetup() throws Exception {
Config conf = ConfigFactory.empty()
.withValue("org.quartz.jobStore.dataSource", ConfigValueFactory.fromAnyRef("db"));
Properties props = new Properties();
props.setProperty("org.quartz.jobStore.dataSource", "db");
new MockUnit(Injector.class, Scheduler.class, Map.class)
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
scheduler.setJobFactory(isA(JobFactory.class));
})
.expect(unit -> {
Map triggers = unit.get(Map.class);
expect(triggers.entrySet()).andReturn(Collections.emptySet());
})
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
StdSchedulerFactory factory = unit.mockConstructor(StdSchedulerFactory.class,
new Class[]{Properties.class }, props);
expect(factory.getScheduler()).andReturn(scheduler);
})
.expect(
unit -> {
Key<Provider<DataSource>> dskey = Key.get(QuartzProvider.DS_TYPE, Names.named("db"));
Provider<DataSource> ds = unit.mock(Provider.class);
Injector injector = unit.get(Injector.class);
expect(injector.getInstance(dskey)).andReturn(ds);
QuartzConnectionProvider cnn = unit.mockConstructor(QuartzConnectionProvider.class,
new Class[]{Provider.class }, ds);
DBConnectionManager dbm = unit.mock(DBConnectionManager.class);
dbm.addConnectionProvider("db", cnn);
unit.mockStatic(DBConnectionManager.class);
expect(DBConnectionManager.getInstance()).andReturn(dbm);
})
.run(unit -> {
new QuartzProvider(unit.get(Injector.class), conf, unit.get(Map.class));
});
}
@SuppressWarnings({"unchecked", "rawtypes" })
@Test(expected = IllegalArgumentException.class)
public void jdbcSetupNoDB() throws Exception {
Config conf = ConfigFactory.empty()
.withValue("org.quartz.jobStore.class",
ConfigValueFactory.fromAnyRef(JobStoreTX.class.getName()));
Properties props = new Properties();
props.setProperty("org.quartz.jobStore.class", JobStoreTX.class.getName());
new MockUnit(Injector.class, Scheduler.class, Map.class)
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
scheduler.setJobFactory(isA(JobFactory.class));
})
.expect(unit -> {
Map triggers = unit.get(Map.class);
expect(triggers.entrySet()).andReturn(Collections.emptySet());
})
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
StdSchedulerFactory factory = unit.mockConstructor(StdSchedulerFactory.class,
new Class[]{Properties.class }, props);
expect(factory.getScheduler()).andReturn(scheduler);
})
.expect(
unit -> {
Key<Provider<DataSource>> dskey = Key.get(QuartzProvider.DS_TYPE, Names.named("db"));
Provider<DataSource> ds = unit.mock(Provider.class);
Injector injector = unit.get(Injector.class);
expect(injector.getInstance(dskey)).andReturn(ds);
QuartzConnectionProvider cnn = unit.mockConstructor(QuartzConnectionProvider.class,
new Class[]{Provider.class }, ds);
DBConnectionManager dbm = unit.mock(DBConnectionManager.class);
dbm.addConnectionProvider("db", cnn);
unit.mockStatic(DBConnectionManager.class);
expect(DBConnectionManager.getInstance()).andReturn(dbm);
})
.run(unit -> {
new QuartzProvider(unit.get(Injector.class), conf, unit.get(Map.class));
});
}
@SuppressWarnings({"unchecked", "rawtypes" })
@Test
public void start() throws Exception {
Config conf = ConfigFactory.empty()
.withValue("org.quartz.jobStore.class", ConfigValueFactory.fromAnyRef("X"));
Properties props = new Properties();
props.setProperty("org.quartz.jobStore.class", "X");
new MockUnit(Injector.class, Scheduler.class, Map.class, JobDetail.class, Trigger.class)
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
scheduler.setJobFactory(isA(JobFactory.class));
})
.expect(
unit -> {
Map triggers = unit.get(Map.class);
JobDetail job = unit.get(JobDetail.class);
expect(job.getKey()).andReturn(JobKey.jobKey("j"));
Trigger trigger = unit.get(Trigger.class);
expect(trigger.getDescription()).andReturn(null);
expect(triggers.entrySet()).andReturn(
Sets.newHashSet(Maps.immutableEntry(job, trigger)));
Scheduler scheduler = unit.get(Scheduler.class);
expect(scheduler.scheduleJob(job, trigger)).andReturn(new Date());
scheduler.start();
})
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
StdSchedulerFactory factory = unit.mockConstructor(StdSchedulerFactory.class,
new Class[]{Properties.class }, props);
expect(factory.getScheduler()).andReturn(scheduler);
})
.run(unit -> {
new QuartzProvider(unit.get(Injector.class), conf, unit.get(Map.class)).start();
});
}
@SuppressWarnings({"unchecked", "rawtypes" })
@Test
public void stop() throws Exception {
Config conf = ConfigFactory.empty()
.withValue("org.quartz.jobStore.class", ConfigValueFactory.fromAnyRef("X"));
Properties props = new Properties();
props.setProperty("org.quartz.jobStore.class", "X");
new MockUnit(Injector.class, Scheduler.class, Map.class)
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
scheduler.setJobFactory(isA(JobFactory.class));
})
.expect(unit -> {
Map triggers = unit.get(Map.class);
expect(triggers.entrySet()).andReturn(Collections.emptySet());
Scheduler scheduler = unit.get(Scheduler.class);
scheduler.shutdown();
})
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
StdSchedulerFactory factory = unit.mockConstructor(StdSchedulerFactory.class,
new Class[]{Properties.class }, props);
expect(factory.getScheduler()).andReturn(scheduler);
})
.run(unit -> {
new QuartzProvider(unit.get(Injector.class), conf, unit.get(Map.class)).stop();
});
}
@SuppressWarnings({"unchecked", "rawtypes" })
@Test
public void get() throws Exception {
Config conf = ConfigFactory.empty()
.withValue("org.quartz.jobStore.class", ConfigValueFactory.fromAnyRef("X"));
Properties props = new Properties();
props.setProperty("org.quartz.jobStore.class", "X");
new MockUnit(Injector.class, Scheduler.class, Map.class)
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
scheduler.setJobFactory(isA(JobFactory.class));
})
.expect(unit -> {
Map triggers = unit.get(Map.class);
expect(triggers.entrySet()).andReturn(Collections.emptySet());
})
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
StdSchedulerFactory factory = unit.mockConstructor(StdSchedulerFactory.class,
new Class[]{Properties.class }, props);
expect(factory.getScheduler()).andReturn(scheduler);
})
.run(unit -> {
assertEquals(unit.get(Scheduler.class), new QuartzProvider(unit.get(Injector.class),
conf, unit.get(Map.class)).get());
});
}
@SuppressWarnings({"unchecked", "rawtypes" })
@Test
public void startTriggerWithDescription() throws Exception {
Config conf = ConfigFactory.empty()
.withValue("org.quartz.jobStore.class", ConfigValueFactory.fromAnyRef("X"));
Properties props = new Properties();
props.setProperty("org.quartz.jobStore.class", "X");
new MockUnit(Injector.class, Scheduler.class, Map.class, JobDetail.class, Trigger.class)
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
scheduler.setJobFactory(isA(JobFactory.class));
})
.expect(
unit -> {
Map triggers = unit.get(Map.class);
JobDetail job = unit.get(JobDetail.class);
expect(job.getKey()).andReturn(JobKey.jobKey("j"));
Trigger trigger = unit.get(Trigger.class);
expect(trigger.getDescription()).andReturn("desc").times(2);
expect(triggers.entrySet()).andReturn(
Sets.newHashSet(Maps.immutableEntry(job, trigger)));
Scheduler scheduler = unit.get(Scheduler.class);
expect(scheduler.scheduleJob(job, trigger)).andReturn(new Date());
scheduler.start();
})
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
StdSchedulerFactory factory = unit.mockConstructor(StdSchedulerFactory.class,
new Class[]{Properties.class }, props);
expect(factory.getScheduler()).andReturn(scheduler);
})
.run(unit -> {
new QuartzProvider(unit.get(Injector.class), conf, unit.get(Map.class)).start();
});
}
@SuppressWarnings({"unchecked", "rawtypes" })
@Test
public void startSimpleTrigger() throws Exception {
Config conf = ConfigFactory.empty()
.withValue("org.quartz.jobStore.class", ConfigValueFactory.fromAnyRef("X"));
Properties props = new Properties();
props.setProperty("org.quartz.jobStore.class", "X");
new MockUnit(Injector.class, Scheduler.class, Map.class, JobDetail.class, SimpleTrigger.class)
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
scheduler.setJobFactory(isA(JobFactory.class));
})
.expect(
unit -> {
Map triggers = unit.get(Map.class);
JobDetail job = unit.get(JobDetail.class);
expect(job.getKey()).andReturn(JobKey.jobKey("j"));
SimpleTrigger trigger = unit.get(SimpleTrigger.class);
expect(trigger.getDescription()).andReturn(null);
expect(trigger.getRepeatInterval()).andReturn(1000L);
expect(triggers.entrySet()).andReturn(
Sets.newHashSet(Maps.immutableEntry(job, trigger)));
Scheduler scheduler = unit.get(Scheduler.class);
expect(scheduler.scheduleJob(job, trigger)).andReturn(new Date());
scheduler.start();
})
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
StdSchedulerFactory factory = unit.mockConstructor(StdSchedulerFactory.class,
new Class[]{Properties.class }, props);
expect(factory.getScheduler()).andReturn(scheduler);
})
.run(unit -> {
new QuartzProvider(unit.get(Injector.class), conf, unit.get(Map.class)).start();
});
}
@SuppressWarnings({"unchecked", "rawtypes" })
@Test
public void startCalendarTrigger() throws Exception {
Config conf = ConfigFactory.empty()
.withValue("org.quartz.jobStore.class", ConfigValueFactory.fromAnyRef("X"));
Properties props = new Properties();
props.setProperty("org.quartz.jobStore.class", "X");
new MockUnit(Injector.class, Scheduler.class, Map.class, JobDetail.class,
CalendarIntervalTrigger.class)
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
scheduler.setJobFactory(isA(JobFactory.class));
})
.expect(
unit -> {
Map triggers = unit.get(Map.class);
JobDetail job = unit.get(JobDetail.class);
expect(job.getKey()).andReturn(JobKey.jobKey("j"));
CalendarIntervalTrigger trigger = unit.get(CalendarIntervalTrigger.class);
expect(trigger.getDescription()).andReturn(null);
expect(trigger.getRepeatInterval()).andReturn(1000);
expect(trigger.getRepeatIntervalUnit()).andReturn(IntervalUnit.DAY);
expect(triggers.entrySet()).andReturn(
Sets.newHashSet(Maps.immutableEntry(job, trigger)));
Scheduler scheduler = unit.get(Scheduler.class);
expect(scheduler.scheduleJob(job, trigger)).andReturn(new Date());
scheduler.start();
})
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
StdSchedulerFactory factory = unit.mockConstructor(StdSchedulerFactory.class,
new Class[]{Properties.class }, props);
expect(factory.getScheduler()).andReturn(scheduler);
})
.run(unit -> {
new QuartzProvider(unit.get(Injector.class), conf, unit.get(Map.class)).start();
});
}
@SuppressWarnings({"unchecked", "rawtypes" })
@Test
public void startDailyTrigger() throws Exception {
Config conf = ConfigFactory.empty()
.withValue("org.quartz.jobStore.class", ConfigValueFactory.fromAnyRef("X"));
Properties props = new Properties();
props.setProperty("org.quartz.jobStore.class", "X");
new MockUnit(Injector.class, Scheduler.class, Map.class, JobDetail.class,
DailyTimeIntervalTrigger.class)
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
scheduler.setJobFactory(isA(JobFactory.class));
})
.expect(
unit -> {
Map triggers = unit.get(Map.class);
JobDetail job = unit.get(JobDetail.class);
expect(job.getKey()).andReturn(JobKey.jobKey("j"));
DailyTimeIntervalTrigger trigger = unit.get(DailyTimeIntervalTrigger.class);
expect(trigger.getDescription()).andReturn(null);
expect(trigger.getRepeatInterval()).andReturn(1000);
expect(trigger.getRepeatIntervalUnit()).andReturn(IntervalUnit.DAY);
expect(triggers.entrySet()).andReturn(
Sets.newHashSet(Maps.immutableEntry(job, trigger)));
Scheduler scheduler = unit.get(Scheduler.class);
expect(scheduler.scheduleJob(job, trigger)).andReturn(new Date());
scheduler.start();
})
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
StdSchedulerFactory factory = unit.mockConstructor(StdSchedulerFactory.class,
new Class[]{Properties.class }, props);
expect(factory.getScheduler()).andReturn(scheduler);
})
.run(unit -> {
new QuartzProvider(unit.get(Injector.class), conf, unit.get(Map.class)).start();
});
}
@SuppressWarnings({"unchecked", "rawtypes" })
@Test
public void startCronTrigger() throws Exception {
Config conf = ConfigFactory.empty()
.withValue("org.quartz.jobStore.class", ConfigValueFactory.fromAnyRef("X"));
Properties props = new Properties();
props.setProperty("org.quartz.jobStore.class", "X");
new MockUnit(Injector.class, Scheduler.class, Map.class, JobDetail.class, CronTrigger.class)
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
scheduler.setJobFactory(isA(JobFactory.class));
})
.expect(
unit -> {
Map triggers = unit.get(Map.class);
JobDetail job = unit.get(JobDetail.class);
expect(job.getKey()).andReturn(JobKey.jobKey("j"));
CronTrigger trigger = unit.get(CronTrigger.class);
expect(trigger.getDescription()).andReturn(null);
expect(trigger.getCronExpression()).andReturn("0/3 0 * * *");
expect(triggers.entrySet()).andReturn(
Sets.newHashSet(Maps.immutableEntry(job, trigger)));
Scheduler scheduler = unit.get(Scheduler.class);
expect(scheduler.scheduleJob(job, trigger)).andReturn(new Date());
scheduler.start();
})
.expect(unit -> {
Scheduler scheduler = unit.get(Scheduler.class);
StdSchedulerFactory factory = unit.mockConstructor(StdSchedulerFactory.class,
new Class[]{Properties.class }, props);
expect(factory.getScheduler()).andReturn(scheduler);
})
.run(unit -> {
new QuartzProvider(unit.get(Injector.class), conf, unit.get(Map.class)).start();
});
}
}