com.whizzosoftware.hobson.scheduler.ical.ICalTaskTest.java Source code

Java tutorial

Introduction

Here is the source code for com.whizzosoftware.hobson.scheduler.ical.ICalTaskTest.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Whizzo Software, LLC.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package com.whizzosoftware.hobson.scheduler.ical;

import com.whizzosoftware.hobson.api.action.HobsonActionRef;
import com.whizzosoftware.hobson.api.action.MockActionManager;
import com.whizzosoftware.hobson.scheduler.executor.MockScheduledTaskExecutor;
import com.whizzosoftware.hobson.scheduler.util.DateHelper;
import net.fortuna.ical4j.data.CalendarBuilder;
import net.fortuna.ical4j.model.Calendar;
import net.fortuna.ical4j.model.DateTime;
import net.fortuna.ical4j.model.Recur;
import net.fortuna.ical4j.model.component.VEvent;
import net.fortuna.ical4j.model.component.VJournal;
import net.fortuna.ical4j.model.property.Comment;
import net.fortuna.ical4j.model.property.RRule;
import net.fortuna.ical4j.model.property.Uid;
import net.fortuna.ical4j.model.property.XProperty;
import net.fortuna.ical4j.util.UidGenerator;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.junit.Test;

import java.io.File;
import java.io.FileReader;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import static org.junit.Assert.*;

public class ICalTaskTest {
    @Test
    public void testConstructorWithNoActions() throws Exception {
        VEvent event = new VEvent(new DateTime(), "task1");
        event.getProperties().add(new Uid("uid"));
        try {
            new ICalTask(null, "", event, null);
            fail("Should have thrown exception");
        } catch (InvalidVEventException ignored) {
        }
    }

    @Test
    public void testConstructorWithActions() throws Exception {
        VEvent event = new VEvent(new DateTime(), "task2");
        event.getProperties().add(new Uid("uid2"));
        event.getProperties().add(new Comment(
                "[{'pluginId':'com.whizzosoftware.hobson.server-api','actionId':'log','name':'My Action','properties':{'message':'foo'}}]"));
        ICalTask task = new ICalTask(null, "", event, null);
        assertEquals("uid2", task.getId());
        assertEquals("task2", task.getName());
        assertNotNull(task.getActions());
        assertEquals(1, task.getActions().size());
        HobsonActionRef action = task.getActions().iterator().next();
        assertEquals("log", action.getActionId());
        assertEquals("My Action", action.getName());
        assertEquals("com.whizzosoftware.hobson.server-api", action.getPluginId());
    }

    @Test
    public void testGetConditions() throws Exception {
        TimeZone tz = TimeZone.getTimeZone("GMT");
        VEvent event = new VEvent(new DateTime(DateHelper.getTime(tz, 2001, 4, 13, 0, 0, 0)), "task1");
        event.getProperties().add(new UidGenerator("1").generateUid());
        event.getProperties().add(new Comment(
                "[{'pluginId':'com.whizzosoftware.hobson.server-api','actionId':'log','name':'My Action','properties':{'message':'foo'}}]"));
        Recur recur = new Recur("FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13");
        event.getProperties().add(new RRule(recur));

        ICalTask task = new ICalTask(null, "", event, null);

        Collection<Map<String, Object>> conditions = task.getConditions();
        assertEquals(1, conditions.size());
        Map<String, Object> map = conditions.iterator().next();
        assertEquals(2, map.size());
        assertEquals("20010412T180000", map.get("start"));
        assertEquals("FREQ=MONTHLY;BYMONTHDAY=13;BYDAY=FR", map.get("recurrence"));
    }

    @Test
    public void testGetConditionsWithSunOffset() throws Exception {
        TimeZone tz = TimeZone.getTimeZone("GMT");
        VEvent event = new VEvent(new DateTime(DateHelper.getTime(tz, 2001, 4, 13, 0, 0, 0)), "task1");
        event.getProperties().add(new UidGenerator("1").generateUid());
        event.getProperties().add(new Comment(
                "[{'pluginId':'com.whizzosoftware.hobson.server-api','actionId':'log','name':'My Action','properties':{'message':'foo'}}]"));
        Recur recur = new Recur("FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13");
        event.getProperties().add(new RRule(recur));
        event.getProperties().add(new XProperty(ICalTask.PROP_SUN_OFFSET, "SS"));

        ICalTask task = new ICalTask(null, "", event, null);

        Collection<Map<String, Object>> conditions = task.getConditions();
        assertEquals(1, conditions.size());
        Map<String, Object> map = conditions.iterator().next();
        assertEquals(3, map.size());
        assertEquals("20010412T180000", map.get("start"));
        assertEquals("FREQ=MONTHLY;BYMONTHDAY=13;BYDAY=FR", map.get("recurrence"));
        assertEquals("SS", map.get("sunOffset"));
    }

    @Test
    public void testNextFridayThe13th() throws Exception {
        TimeZone tz = TimeZone.getTimeZone("GMT");

        // event starts on 4/13/2001 and goes monthly every friday the 13th
        VEvent event = new VEvent(new DateTime(DateHelper.getTime(tz, 2001, 4, 13, 0, 0, 0)), "task1");
        event.getProperties().add(new UidGenerator("1").generateUid());
        event.getProperties().add(new Comment(
                "[{'pluginId':'com.whizzosoftware.hobson.server-api','actionId':'log','name':'My Action','properties':{'message':'foo'}}]"));
        Recur recur = new Recur("FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13");
        event.getProperties().add(new RRule(recur));

        // check from day before first occurrence
        ICalTask task = new ICalTask(null, "", event, null);
        List<Long> periods = task.getRunsDuringInterval(DateHelper.getTime(tz, 2001, 4, 12, 0, 0, 0),
                DateHelper.getTime(tz, 2001, 4, 14, 0, 0, 0));
        assertEquals(1, periods.size());

        // check from day of first occurrence
        long startDate = DateHelper.getTime(tz, 2001, 4, 13, 0, 0, 0);
        periods = task.getRunsDuringInterval(startDate, DateHelper.getTime(tz, 2001, 4, 14, 0, 0, 0));
        assertEquals(1, periods.size());

        // check from much later date
        startDate = DateHelper.getTime(tz, 2014, 6, 30, 0, 0, 0);
        periods = task.getRunsDuringInterval(startDate, startDate + (1000 * 60 * 60 * 24));
        assertEquals(0, periods.size());
    }

    @Test
    public void testEvery3DaysAt9AM() throws Exception {
        TimeZone tz = TimeZone.getTimeZone("GMT");

        // create event
        VEvent event = new VEvent(new DateTime(DateHelper.getTime(tz, 2014, 6, 1, 9, 0, 0)), "task1");
        event.getProperties().add(new UidGenerator("1").generateUid());
        event.getProperties().add(new Comment(
                "[{'pluginId':'com.whizzosoftware.hobson.server-api','actionId':'log','name':'My Action','properties':{'message':'foo'}}]"));
        Recur recur = new Recur("FREQ=DAILY;INTERVAL=3");
        event.getProperties().add(new RRule(recur));

        // check from day before first occurrence
        ICalTask task = new ICalTask(null, "", event, null);
        List<Long> periods = task.getRunsDuringInterval(DateHelper.getTime(tz, 2014, 6, 1, 9, 0, 0),
                DateHelper.getTime(tz, 2014, 8, 31, 23, 59, 59));
        assertEquals(31, periods.size());
        assertEquals(DateHelper.getTime(tz, 2014, 6, 1, 9, 0, 0), (long) periods.get(0));
        assertEquals(DateHelper.getTime(tz, 2014, 6, 4, 9, 0, 0), (long) periods.get(1));
        assertEquals(DateHelper.getTime(tz, 2014, 6, 7, 9, 0, 0), (long) periods.get(2));
        assertEquals(DateHelper.getTime(tz, 2014, 6, 10, 9, 0, 0), (long) periods.get(3));
        assertEquals(DateHelper.getTime(tz, 2014, 6, 13, 9, 0, 0), (long) periods.get(4));
        assertEquals(DateHelper.getTime(tz, 2014, 6, 16, 9, 0, 0), (long) periods.get(5));
        assertEquals(DateHelper.getTime(tz, 2014, 6, 19, 9, 0, 0), (long) periods.get(6));
        assertEquals(DateHelper.getTime(tz, 2014, 6, 22, 9, 0, 0), (long) periods.get(7));
        assertEquals(DateHelper.getTime(tz, 2014, 6, 25, 9, 0, 0), (long) periods.get(8));
        assertEquals(DateHelper.getTime(tz, 2014, 6, 28, 9, 0, 0), (long) periods.get(9));
        assertEquals(DateHelper.getTime(tz, 2014, 7, 1, 9, 0, 0), (long) periods.get(10));
        assertEquals(DateHelper.getTime(tz, 2014, 7, 4, 9, 0, 0), (long) periods.get(11));
        assertEquals(DateHelper.getTime(tz, 2014, 7, 7, 9, 0, 0), (long) periods.get(12));
        assertEquals(DateHelper.getTime(tz, 2014, 7, 10, 9, 0, 0), (long) periods.get(13));
        assertEquals(DateHelper.getTime(tz, 2014, 7, 13, 9, 0, 0), (long) periods.get(14));
        assertEquals(DateHelper.getTime(tz, 2014, 7, 16, 9, 0, 0), (long) periods.get(15));
        assertEquals(DateHelper.getTime(tz, 2014, 7, 19, 9, 0, 0), (long) periods.get(16));
        assertEquals(DateHelper.getTime(tz, 2014, 7, 22, 9, 0, 0), (long) periods.get(17));
        assertEquals(DateHelper.getTime(tz, 2014, 7, 25, 9, 0, 0), (long) periods.get(18));
        assertEquals(DateHelper.getTime(tz, 2014, 7, 28, 9, 0, 0), (long) periods.get(19));
        assertEquals(DateHelper.getTime(tz, 2014, 7, 31, 9, 0, 0), (long) periods.get(20));
        assertEquals(DateHelper.getTime(tz, 2014, 8, 3, 9, 0, 0), (long) periods.get(21));
        assertEquals(DateHelper.getTime(tz, 2014, 8, 6, 9, 0, 0), (long) periods.get(22));
        assertEquals(DateHelper.getTime(tz, 2014, 8, 9, 9, 0, 0), (long) periods.get(23));
        assertEquals(DateHelper.getTime(tz, 2014, 8, 12, 9, 0, 0), (long) periods.get(24));
        assertEquals(DateHelper.getTime(tz, 2014, 8, 15, 9, 0, 0), (long) periods.get(25));
        assertEquals(DateHelper.getTime(tz, 2014, 8, 18, 9, 0, 0), (long) periods.get(26));
        assertEquals(DateHelper.getTime(tz, 2014, 8, 21, 9, 0, 0), (long) periods.get(27));
        assertEquals(DateHelper.getTime(tz, 2014, 8, 24, 9, 0, 0), (long) periods.get(28));
        assertEquals(DateHelper.getTime(tz, 2014, 8, 27, 9, 0, 0), (long) periods.get(29));
        assertEquals(DateHelper.getTime(tz, 2014, 8, 30, 9, 0, 0), (long) periods.get(30));
        assertEquals(DateHelper.getTime(tz, 2014, 8, 30, 9, 0, 0), (long) periods.get(30));
    }

    @Test
    public void testJSONRuleConstruction() throws Exception {
        ICalTaskProvider provider = new ICalTaskProvider("pluginId", null, null);
        provider.setScheduleExecutor(new MockScheduledTaskExecutor());

        // validate we start with a non-existent temp file
        File calendarFile = File.createTempFile("schedule", ".ics");
        assertTrue(calendarFile.delete());
        assertFalse(calendarFile.exists());

        try {
            provider.setScheduleFile(calendarFile);
            provider.reloadScheduleFile();
            JSONObject json = new JSONObject(new JSONTokener(
                    "{'name':'My Task','conditions':[{'start':'20140701T100000','recurrence':'FREQ=MINUTELY;INTERVAL=1'}],'actions':[{'pluginId':'com.whizzosoftware.hobson.server-api','actionId':'log','name':'My Action','properties':{'message':'logentry'}}]}"));
            provider.addTask(json);

            // make sure the provider updated the rule file
            assertTrue(calendarFile.exists());
            Calendar cal = new CalendarBuilder().build(new FileReader(calendarFile));

            assertEquals(2, cal.getComponents().size());
            assertTrue(cal.getComponents().get(0) instanceof VJournal);
            assertTrue(cal.getComponents().get(1) instanceof VEvent);

            VEvent event = (VEvent) cal.getComponents().get(1);
            assertNotNull(event.getUid().getValue());
            assertEquals("My Task", event.getSummary().getValue());

            assertEquals("20140701T100000", event.getProperties().getProperty("DTSTART").getValue());
            assertEquals("FREQ=MINUTELY;INTERVAL=1", event.getProperties().getProperty("RRULE").getValue());

            assertNotNull(event.getProperties().getProperty("COMMENT"));
            JSONArray jarray = new JSONArray(
                    new JSONTokener(event.getProperties().getProperty("COMMENT").getValue()));
            assertEquals(1, jarray.length());
            JSONObject ajson = jarray.getJSONObject(0);
            assertEquals("com.whizzosoftware.hobson.server-api", ajson.getString("pluginId"));
            assertEquals("log", ajson.getString("actionId"));
            assertTrue(ajson.has("properties"));
            JSONObject props = ajson.getJSONObject("properties");
            assertEquals("logentry", props.getString("message"));
        } finally {
            assertTrue(calendarFile.delete());
        }
    }

    @Test
    public void testJSONRuleConstructionWithSunOffset() throws Exception {
        ICalTaskProvider provider = new ICalTaskProvider("pluginId", null, null);
        provider.setScheduleExecutor(new MockScheduledTaskExecutor());

        // validate we start with a non-existent temp file
        File calendarFile = File.createTempFile("schedule", ".ics");
        assertTrue(calendarFile.delete());
        assertFalse(calendarFile.exists());

        try {
            provider.setScheduleFile(calendarFile);
            provider.reloadScheduleFile();
            JSONObject json = new JSONObject(new JSONTokener(
                    "{'name':'My Task','conditions':[{'start':'20140701T100000','recurrence':'FREQ=MINUTELY;INTERVAL=1','sunOffset':'SR'}],'actions':[{'pluginId':'com.whizzosoftware.hobson.server-api','actionId':'log','name':'My Action','properties':{'message':'logentry'}}]}"));
            provider.addTask(json);

            // make sure the provider updated the rule file
            assertTrue(calendarFile.exists());
            Calendar cal = new CalendarBuilder().build(new FileReader(calendarFile));

            assertEquals(2, cal.getComponents().size());
            assertTrue(cal.getComponents().get(0) instanceof VJournal);
            assertTrue(cal.getComponents().get(1) instanceof VEvent);

            VEvent event = (VEvent) cal.getComponents().get(1);
            assertNotNull(event.getUid().getValue());
            assertEquals("My Task", event.getSummary().getValue());

            assertEquals("20140701T100000", event.getProperties().getProperty("DTSTART").getValue());
            assertEquals("FREQ=MINUTELY;INTERVAL=1", event.getProperties().getProperty("RRULE").getValue());
            assertEquals("SR", event.getProperties().getProperty(ICalTask.PROP_SUN_OFFSET).getValue());

            assertNotNull(event.getProperties().getProperty("COMMENT"));
            JSONArray jarray = new JSONArray(
                    new JSONTokener(event.getProperties().getProperty("COMMENT").getValue()));
            assertEquals(1, jarray.length());
            JSONObject ajson = jarray.getJSONObject(0);
            assertEquals("com.whizzosoftware.hobson.server-api", ajson.getString("pluginId"));
            assertEquals("log", ajson.getString("actionId"));
            assertTrue(ajson.has("properties"));
            JSONObject props = ajson.getJSONObject("properties");
            assertEquals("logentry", props.getString("message"));
        } finally {
            assertTrue(calendarFile.delete());
        }
    }

    @Test
    public void testSunOffset() throws Exception {
        MockActionManager am = new MockActionManager();
        TimeZone tz = TimeZone.getTimeZone("America/Denver");
        VEvent event = new VEvent(new DateTime(DateHelper.getTime(tz, 2014, 10, 19, 0, 0, 0)), "task1");
        event.getProperties().add(new UidGenerator("1").generateUid());
        event.getProperties().add(new Comment(
                "[{'pluginId':'com.whizzosoftware.hobson.server-api','actionId':'log','name':'My Action','properties':{'message':'foo'}}]"));
        event.getProperties().add(new XProperty(ICalTask.PROP_SUN_OFFSET, "SS+30"));
        Recur recur = new Recur("FREQ=DAILY;INTERVAL=1");
        event.getProperties().add(new RRule(recur));

        ICalTask task = new ICalTask(am, "providerId", event, null);
        task.setLatitude(39.3722);
        task.setLongitude(-104.8561);

        List<Long> runs = task.getRunsDuringInterval(DateHelper.getTime(tz, 2014, 10, 19, 0, 0, 0),
                DateHelper.getTime(tz, 2014, 10, 19, 23, 59, 59));
        assertEquals(1, runs.size());
        assertEquals(1413765900000l, (long) runs.get(0));

        runs = task.getRunsDuringInterval(DateHelper.getTime(tz, 2014, 12, 19, 0, 0, 0),
                DateHelper.getTime(tz, 2014, 12, 19, 23, 59, 59));
        assertEquals(1, runs.size());
        assertEquals(1419034080000l, (long) runs.get(0));

        runs = task.getRunsDuringInterval(DateHelper.getTime(tz, 2015, 7, 19, 0, 0, 0),
                DateHelper.getTime(tz, 2015, 7, 19, 23, 59, 59));
        assertEquals(1, runs.size());
        assertEquals(1437360780000l, (long) runs.get(0));

        // This one is interesting -- since we store the start time for events with a sun offset as midnight, this event
        // technically would have already run as it's strictly defined by the VEvent. However, with the sun offset the
        // start time is pushed until after the current time and it SHOULD run
        runs = task.getRunsDuringInterval(DateHelper.getTime(tz, 2014, 10, 20, 16, 46, 0),
                DateHelper.getTime(tz, 2014, 10, 20, 23, 59, 59));
        assertEquals(1, runs.size());
    }

    @Test
    public void testGetRunsForIntervalWithNoLatLong() throws Exception {
        MockActionManager am = new MockActionManager();
        TimeZone tz = TimeZone.getTimeZone("America/Denver");
        VEvent event = new VEvent(new DateTime(DateHelper.getTime(tz, 2014, 10, 19, 0, 0, 0)), "task1");
        event.getProperties().add(new UidGenerator("1").generateUid());
        event.getProperties().add(new Comment(
                "[{'pluginId':'com.whizzosoftware.hobson.server-api','actionId':'log','name':'My Action','properties':{'message':'foo'}}]"));
        event.getProperties().add(new XProperty(ICalTask.PROP_SUN_OFFSET, "SS+30"));
        Recur recur = new Recur("FREQ=DAILY;INTERVAL=1");
        event.getProperties().add(new RRule(recur));

        ICalTask task = new ICalTask(am, "providerId", event, null);

        List<Long> runs = null;
        try {
            runs = task.getRunsDuringInterval(DateHelper.getTime(tz, 2014, 10, 19, 0, 0, 0),
                    DateHelper.getTime(tz, 2014, 10, 19, 23, 59, 59));
            fail("Should have thrown exception");
        } catch (SchedulingException ignored) {
        }
    }
}