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(); }); } }