/*
* 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 org.f1x.v1.schedule;
import org.f1x.store.InMemoryMessageStore;
import org.f1x.store.MessageStore;
import org.f1x.util.StoredTimeSource;
import org.f1x.util.TestUtils;
import org.f1x.v1.FixSessionInitiator;
import org.junit.Assert;
import org.junit.Test;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class Test_SimpleSessionSchedule {
private static final String LONG_TIME_AGO = "20101212-00:00:00.000"; // some random time in the past (exact moment is not important)
private StoredTimeSource timeSource = new StoredTimeSource() {
{
setLocalTime(LONG_TIME_AGO);
}
};
private SimpleSessionSchedule schedule;
@Test(expected = IllegalArgumentException.class)
public void testEveryDayMostRecentSessionBefore_Weekly () {
makeSchedule(-1, -1, "11:00:00", "22:00:00", false);
}
@Test(expected = IllegalArgumentException.class)
public void testOneSidedWeekdayStart () {
makeSchedule(Calendar.MONDAY, -1, "11:00:00", "22:00:00", true);
}
@Test(expected = IllegalArgumentException.class)
public void testOneSidedWeekdayEnd () {
makeSchedule(-1, Calendar.FRIDAY, "11:00:00", "22:00:00", true);
}
/** Test "every day same hours" schedule */
@Test
public void testEveryDayMostRecentSessionBefore () {
schedule = makeSchedule(-1, -1, "09:00:00", "23:00:00", true);
assertMostRecentSession ("20140121-08:59:00.000", "20140120-09:00:00.000", "20140120-23:00:00.000"); // shortly before session start
assertMostRecentSession ("20140121-09:01:00.000", "20140121-09:00:00.000", "20140121-23:00:00.000"); // shortly after session start
assertMostRecentSession ("20140121-22:59:00.000", "20140121-09:00:00.000", "20140121-23:00:00.000"); // shortly before session close
assertMostRecentSession ("20140121-23:01:00.000", "20140121-09:00:00.000", "20140121-23:00:00.000"); // shortly after session close
assertMostRecentSession ("20140121-00:00:00.000", "20140120-09:00:00.000", "20140120-23:00:00.000"); // midnight
assertMostRecentSession ("20140121-12:00:00.000", "20140121-09:00:00.000", "20140121-23:00:00.000"); // noon
}
/** Test "every day same hours" schedule where start time is later than end time */
@Test
public void testEveryDayMostRecentSessionBefore_Inverted () {
schedule = makeSchedule(-1, -1, "23:00:00", "22:00:00", true); // starts 23:00 and continues until 22:00 next day
assertMostRecentSession ("20140121-22:59:00.000", "20140120-23:00:00.000", "20140121-22:00:00.000"); // shortly before session start
assertMostRecentSession ("20140121-23:01:00.000", "20140121-23:00:00.000", "20140122-22:00:00.000"); // shortly after session start
assertMostRecentSession ("20140122-21:59:00.000", "20140121-23:00:00.000", "20140122-22:00:00.000"); // shortly before session close
assertMostRecentSession ("20140122-22:01:00.000", "20140121-23:00:00.000", "20140122-22:00:00.000"); // shortly after session close
assertMostRecentSession ("20140121-00:00:00.000", "20140120-23:00:00.000", "20140121-22:00:00.000"); // midnight
assertMostRecentSession ("20140121-12:00:00.000", "20140120-23:00:00.000", "20140121-22:00:00.000"); // noon
}
/** Test "Monday to Friday hours" schedule */
@Test
public void testMondayFridayMostRecentSessionBefore () {
schedule = makeSchedule(Calendar.MONDAY, Calendar.FRIDAY, "09:00:00", "23:00:00", true);
assertMostRecentSession ("20140121-08:59:00.000", "20140120-09:00:00.000", "20140120-23:00:00.000"); // shortly before session start
assertMostRecentSession ("20140121-09:01:00.000", "20140121-09:00:00.000", "20140121-23:00:00.000"); // shortly after session start
assertMostRecentSession ("20140121-22:59:00.000", "20140121-09:00:00.000", "20140121-23:00:00.000"); // shortly before session close
assertMostRecentSession ("20140121-23:01:00.000", "20140121-09:00:00.000", "20140121-23:00:00.000"); // shortly after session close
assertMostRecentSession ("20140121-00:00:00.000", "20140120-09:00:00.000", "20140120-23:00:00.000"); // midnight
assertMostRecentSession ("20140121-12:00:00.000", "20140121-09:00:00.000", "20140121-23:00:00.000"); // noon
// Special cases:
assertMostRecentSession ("20140120-08:59:00.000", "20140117-09:00:00.000", "20140117-23:00:00.000"); // shortly before session open on Monday get us Friday session
}
/** Test "Monday to Friday hours" schedule where start time is later than end time */
@Test
public void testMondayFridayMostRecentSessionBefore_Inverted () {
schedule = makeSchedule(Calendar.MONDAY, Calendar.FRIDAY, "23:00:00", "22:00:00", true); // starts 23:00 and continues until 22:00 next day (THIS IS ACTUALLY 4 DAYS PER WEEK, NOT 5!)
assertMostRecentSession ("20140121-22:59:00.000", "20140120-23:00:00.000", "20140121-22:00:00.000"); // shortly before session start
assertMostRecentSession ("20140121-23:01:00.000", "20140121-23:00:00.000", "20140122-22:00:00.000"); // shortly after session start
assertMostRecentSession ("20140122-21:59:00.000", "20140121-23:00:00.000", "20140122-22:00:00.000"); // shortly before session close
assertMostRecentSession ("20140122-22:01:00.000", "20140121-23:00:00.000", "20140122-22:00:00.000"); // shortly after session close
assertMostRecentSession ("20140121-00:00:00.000", "20140120-23:00:00.000", "20140121-22:00:00.000"); // midnight
assertMostRecentSession ("20140121-12:00:00.000", "20140120-23:00:00.000", "20140121-22:00:00.000"); // noon
// Special cases:
assertMostRecentSession ("20140120-21:59:00.000", "20140116-23:00:00.000", "20140117-22:00:00.000"); // shortly before session open on Monday returns Thursday-Friday session
assertMostRecentSession ("20140121-21:59:00.000", "20140120-23:00:00.000", "20140121-22:00:00.000"); // shortly before session open on Tuesday returns Monday-Tuesday session
assertMostRecentSession ("20140122-21:59:00.000", "20140121-23:00:00.000", "20140122-22:00:00.000"); // shortly before session open on Wed returns Tues-Wed session
assertMostRecentSession ("20140123-21:59:00.000", "20140122-23:00:00.000", "20140123-22:00:00.000"); // shortly before session open on Thurs returns Wed-Thurs session
assertMostRecentSession ("20140124-21:59:00.000", "20140123-23:00:00.000", "20140124-22:00:00.000"); // shortly before session open on Friday returns Thurs-Fri session
assertMostRecentSession ("20140125-21:59:00.000", "20140123-23:00:00.000", "20140124-22:00:00.000"); // shortly before 22:00 on Saturday returns Thurs-Fri session AGAIN!
assertMostRecentSession ("20140120-12:00:00.000", "20140116-23:00:00.000", "20140117-22:00:00.000");
assertMostRecentSession ("20140120-21:59:00.000", "20140116-23:00:00.000", "20140117-22:00:00.000");
assertMostRecentSession ("20140120-21:59:00.000", "20140116-23:00:00.000", "20140117-22:00:00.000");
}
/** Test weekly "Monday to Friday" schedule */
@Test
public void testMondayFridayWeeklyMostRecentSessionBefore () {
schedule = makeSchedule(Calendar.MONDAY, Calendar.FRIDAY, "09:00:00", "23:00:00", false);
assertMostRecentSession ("20140120-08:59:00.000", "20140113-09:00:00.000", "20140117-23:00:00.000"); // shortly before session start
assertMostRecentSession ("20140120-09:01:00.000", "20140120-09:00:00.000", "20140124-23:00:00.000"); // shortly after session start
assertMostRecentSession ("20140124-22:59:00.000", "20140120-09:00:00.000", "20140124-23:00:00.000"); // shortly before session close
assertMostRecentSession ("20140124-23:01:00.000", "20140120-09:00:00.000", "20140124-23:00:00.000"); // shortly after session close
assertMostRecentSession ("20140120-00:00:00.000", "20140113-09:00:00.000", "20140117-23:00:00.000"); // midnight Jan 20
assertMostRecentSession ("20140120-12:00:00.000", "20140120-09:00:00.000", "20140124-23:00:00.000"); // noon Jan 20
assertMostRecentSession ("20140121-00:00:00.000", "20140120-09:00:00.000", "20140124-23:00:00.000"); // midnight Jan 21
assertMostRecentSession ("20140121-12:00:00.000", "20140120-09:00:00.000", "20140124-23:00:00.000"); // noon Jan 21
}
/** Test weekly "Monday to Friday" schedule where start time is later than end time */
@Test
public void testMondayFridayWeeklyMostRecentSessionBefore_Inverted () {
schedule = makeSchedule(Calendar.MONDAY, Calendar.FRIDAY, "23:00:00", "22:00:00", false); // starts Monday 23:00 and continues until Friday 22:00
assertMostRecentSession ("20140120-22:59:00.000", "20140113-23:00:00.000", "20140117-22:00:00.000"); // shortly before session start
assertMostRecentSession ("20140120-23:01:00.000", "20140120-23:00:00.000", "20140124-22:00:00.000"); // shortly after session start
assertMostRecentSession ("20140124-21:59:00.000", "20140120-23:00:00.000", "20140124-22:00:00.000"); // shortly before session close
assertMostRecentSession ("20140124-22:01:00.000", "20140120-23:00:00.000", "20140124-22:00:00.000"); // shortly after session close
assertMostRecentSession ("20140120-00:00:00.000", "20140113-23:00:00.000", "20140117-22:00:00.000"); // midnight Jan 20
assertMostRecentSession ("20140120-12:00:00.000", "20140113-23:00:00.000", "20140117-22:00:00.000"); // noon Jan 20
assertMostRecentSession ("20140121-00:00:00.000", "20140120-23:00:00.000", "20140124-22:00:00.000"); // midnight Jan 21
assertMostRecentSession ("20140121-12:00:00.000", "20140120-23:00:00.000", "20140124-22:00:00.000"); // noon Jan 21
}
/// NextSession
/** Test "every day same hours" schedule */
@Test
public void testEveryDayNextSessionAfter () {
schedule = makeSchedule(-1, -1, "09:00:00", "23:00:00", true);
assertNextSession ("20140121-08:59:00.000", "20140121-09:00:00.000", "20140121-23:00:00.000"); // shortly before session start
assertNextSession ("20140121-09:01:00.000", "20140122-09:00:00.000", "20140122-23:00:00.000"); // shortly after session start => next session instead of current
assertNextSession ("20140121-22:59:00.000", "20140122-09:00:00.000", "20140122-23:00:00.000"); // shortly before session close => next session instead of current
assertNextSession ("20140121-23:01:00.000", "20140122-09:00:00.000", "20140122-23:00:00.000"); // shortly after session close
assertNextSession ("20140121-00:00:00.000", "20140121-09:00:00.000", "20140121-23:00:00.000"); // midnight
assertNextSession ("20140121-12:00:00.000", "20140122-09:00:00.000", "20140122-23:00:00.000"); // noon => next session instead of current
}
/** Test "every day same hours" schedule where start time is later than end time */
@Test
public void testEveryDayNextSessionAfter_Inverted () {
schedule = makeSchedule(-1, -1, "23:00:00", "22:00:00", true); // starts 23:00 and continues until 22:00 next day
assertNextSession ("20140121-22:59:00.000", "20140121-23:00:00.000", "20140122-22:00:00.000"); // shortly before session start
assertNextSession ("20140121-23:01:00.000", "20140122-23:00:00.000", "20140123-22:00:00.000"); // shortly after session start => next session instead of current
assertNextSession ("20140122-21:59:00.000", "20140122-23:00:00.000", "20140123-22:00:00.000"); // shortly before session close => next session instead of current
assertNextSession ("20140122-22:01:00.000", "20140122-23:00:00.000", "20140123-22:00:00.000"); // shortly after session close
assertNextSession ("20140121-00:00:00.000", "20140121-23:00:00.000", "20140122-22:00:00.000"); // midnight
assertNextSession ("20140121-12:00:00.000", "20140121-23:00:00.000", "20140122-22:00:00.000"); // noon
}
/** Test "Monday to Friday hours" schedule */
@Test
public void testMondayFridayNextSessionAfter () {
schedule = makeSchedule(Calendar.MONDAY, Calendar.FRIDAY, "09:00:00", "23:00:00", true);
assertNextSession ("20140121-08:59:00.000", "20140121-09:00:00.000", "20140121-23:00:00.000"); // shortly before session start
assertNextSession ("20140121-09:01:00.000", "20140122-09:00:00.000", "20140122-23:00:00.000"); // shortly after session start => next session instead of current
assertNextSession ("20140121-22:59:00.000", "20140122-09:00:00.000", "20140122-23:00:00.000"); // shortly before session close => next session instead of current
assertNextSession ("20140121-23:01:00.000", "20140122-09:00:00.000", "20140122-23:00:00.000"); // shortly after session close
assertNextSession ("20140121-00:00:00.000", "20140121-09:00:00.000", "20140121-23:00:00.000"); // midnight
assertNextSession ("20140121-12:00:00.000", "20140122-09:00:00.000", "20140122-23:00:00.000"); // noon => next session instead of current
// Special cases:
assertNextSession ("20140124-23:00:00.000", "20140127-09:00:00.000", "20140127-23:00:00.000"); // session close on Friday get us next Monday session
}
/** Test "Monday to Friday hours" schedule where start time is later than end time */
@Test
public void testMondayFridayNextSessionAfter_Inverted () {
schedule = makeSchedule(Calendar.MONDAY, Calendar.FRIDAY, "23:00:00", "22:00:00", true); // starts 23:00 and continues until 22:00 next day (THIS IS ACTUALLY 4 DAYS PER WEEK, NOT 5!)
assertNextSession ("20140121-22:59:00.000", "20140121-23:00:00.000", "20140122-22:00:00.000"); // shortly before session start
assertNextSession ("20140121-23:01:00.000", "20140122-23:00:00.000", "20140123-22:00:00.000"); // shortly after session start
assertNextSession ("20140122-21:59:00.000", "20140122-23:00:00.000", "20140123-22:00:00.000"); // shortly before session close
assertNextSession ("20140122-22:01:00.000", "20140122-23:00:00.000", "20140123-22:00:00.000"); // shortly after session close
assertNextSession ("20140121-00:00:00.000", "20140121-23:00:00.000", "20140122-22:00:00.000"); // midnight
assertNextSession ("20140121-12:00:00.000", "20140121-23:00:00.000", "20140122-22:00:00.000"); // noon
// Special cases:
assertNextSession ("20140120-21:59:00.000", "20140120-23:00:00.000", "20140121-22:00:00.000"); // shortly before session open on Monday returns Mon-Tues session (1)
assertNextSession ("20140121-21:59:00.000", "20140121-23:00:00.000", "20140122-22:00:00.000"); // shortly before session open on Tuesday returns Tues-Wed session (2)
assertNextSession ("20140122-21:59:00.000", "20140122-23:00:00.000", "20140123-22:00:00.000"); // shortly before session open on Wed returns Wed-Thurs session (3)
assertNextSession ("20140123-21:59:00.000", "20140123-23:00:00.000", "20140124-22:00:00.000"); // shortly before session open on Thurs returns Thurs-Frid session (4)
assertNextSession ("20140124-21:59:00.000", "20140127-23:00:00.000", "20140128-22:00:00.000"); // shortly before session open on Friday returns Mon-Tues session
}
/** Test weekly "Monday to Friday" schedule */
@Test
public void testMondayFridayWeeklyNextSessionAfter () {
schedule = makeSchedule(Calendar.MONDAY, Calendar.FRIDAY, "09:00:00", "23:00:00", false);
assertNextSession ("20140120-08:59:00.000", "20140120-09:00:00.000", "20140124-23:00:00.000"); // shortly before session start on Monday
assertNextSession ("20140120-09:01:00.000", "20140127-09:00:00.000", "20140131-23:00:00.000"); // shortly after session start on Monday
assertNextSession ("20140124-22:59:00.000", "20140127-09:00:00.000", "20140131-23:00:00.000"); // shortly before session close on Friday
assertNextSession ("20140124-23:01:00.000", "20140127-09:00:00.000", "20140131-23:00:00.000"); // shortly after session close on Friday
assertNextSession ("20140120-00:00:00.000", "20140120-09:00:00.000", "20140124-23:00:00.000"); // midnight Jan 20
assertNextSession ("20140120-12:00:00.000", "20140127-09:00:00.000", "20140131-23:00:00.000"); // noon Jan 20
}
/** Test weekly "Monday to Friday" schedule where start time is later than end time */
@Test
public void testMondayFridayWeeklyNextSessionAfter_Inverted () {
schedule = makeSchedule(Calendar.MONDAY, Calendar.FRIDAY, "23:00:00", "22:00:00", false); // starts Monday 23:00 and continues until Friday 22:00
assertNextSession ("20140120-22:59:00.000", "20140120-23:00:00.000", "20140124-22:00:00.000"); // shortly before session start on Monday
assertNextSession ("20140120-23:01:00.000", "20140127-23:00:00.000", "20140131-22:00:00.000"); // shortly after session start on Monday
assertNextSession ("20140124-21:59:00.000", "20140127-23:00:00.000", "20140131-22:00:00.000"); // shortly before session close on Friday
assertNextSession ("20140124-22:01:00.000", "20140127-23:00:00.000", "20140131-22:00:00.000"); // shortly after session close on Friday
assertNextSession ("20140120-00:00:00.000", "20140120-23:00:00.000", "20140124-22:00:00.000"); // midnight Jan 20
assertNextSession ("20140120-12:00:00.000", "20140120-23:00:00.000", "20140124-22:00:00.000"); // noon Jan 20
assertNextSession ("20140121-00:00:00.000", "20140127-23:00:00.000", "20140131-22:00:00.000"); // midnight Jan 20
assertNextSession ("20140121-12:00:00.000", "20140127-23:00:00.000", "20140131-22:00:00.000"); // noon Jan 20
}
@Test
public void testWaitTime() throws InterruptedException {
schedule = makeSchedule(Calendar.MONDAY, Calendar.FRIDAY, "09:00:00", "23:00:00", true);
assertSessionWaitAndEndTime("20140120-09:01:00.000", "20140120-23:00:00.000", 0); // Monday shortly after open
assertSessionWaitAndEndTime("20140121-08:59:00.000", "20140121-23:00:00.000", 1*60000); // Tuesday shortly before open
assertSessionWaitAndEndTime("20140121-09:01:00.000", "20140121-23:00:00.000", 0); // Tuesday shortly after open
assertSessionWaitAndEndTime("20140117-22:59:00.000", "20140117-23:00:00.000", 0); // Friday before close
assertSessionWaitAndEndTime("20140117-23:01:00.000", "20140120-23:00:00.000", (1+24+24+9)*3600000 - 1*60000); // Friday after close
}
/** Test weekly "Monday to Friday" schedule where start time is later than end time */
@Test
public void testFridayBeforeEnd () throws InterruptedException {
schedule = makeSchedule(Calendar.SUNDAY, Calendar.FRIDAY, "17:30:00", "16:59:00", true); // Sun-Fri daily from 17:30 till 16:59 next day
assertNextSession ("20140314-13:30:00.000", "20140316-17:30:00.000", "20140317-16:59:00.000"); // Friday midday
assertSessionWaitAndEndTime("20140314-13:30:00.000", "20140314-16:59:00.000", 0); // Friday before close
}
/// Helpers
private void assertMostRecentSession (String currentTime, String expectedStart, String expectedEnd) {
long now = TestUtils.parseLocalTimestamp(currentTime);
synchronized (schedule) { // make assert happy
schedule.setMostRecentSessionBefore(now);
}
long actualStart = schedule.start.getTimeInMillis();
long actualEnd = schedule.end.getTimeInMillis();
Assert.assertEquals("Start of most recent session for " + new Date(now), expectedStart, TestUtils.formatLocalTimestamp(actualStart));
Assert.assertEquals("End of most recent session for " + new Date(now), expectedEnd, TestUtils.formatLocalTimestamp(actualEnd));
}
private void assertNextSession (String currentTime, String expectedStart, String expectedEnd) {
long now = TestUtils.parseLocalTimestamp(currentTime);
synchronized (schedule) { // make assert happy
schedule.setNextSessionAfter(now);
}
long actualStart = schedule.start.getTimeInMillis();
long actualEnd = schedule.end.getTimeInMillis();
Assert.assertEquals("Start of next session for " + new Date(now), expectedStart, TestUtils.formatLocalTimestamp(actualStart));
Assert.assertEquals("End of next session for " + new Date(now), expectedEnd, TestUtils.formatLocalTimestamp(actualEnd));
}
private void assertSessionWaitAndEndTime(String currentTime, String expectedSessionEndTime, long delayBeforeStart) throws InterruptedException {
timeSource.setLocalTime(currentTime);
SessionTimes sessionTimes = schedule.getCurrentSessionTimes(timeSource.currentTimeMillis());
long now = timeSource.currentTimeMillis();
Assert.assertEquals("Session start time", delayBeforeStart, Math.max(0, sessionTimes.getStart() - now));
String actualSessionEndTime = TestUtils.formatLocalTimestamp(sessionTimes.getEnd());
Assert.assertEquals("Session end time", expectedSessionEndTime, actualSessionEndTime);
}
// private void assertNewSession (SessionSchedule ss, String lastConnectionTimestamp, String currentTime) throws InterruptedException {
// timeSource.setLocalTime(currentTime);
// boolean newSession = ss.getCurrentSessionTimes(TestUtils.parseLocalTimestamp(lastConnectionTimestamp));
// Assert.assertTrue("same session", newSession);
// }
//
// private void assertOldSession (SessionSchedule ss, String lastConnectionTimestamp, String currentTime) throws InterruptedException {
// timeSource.setLocalTime(currentTime);
// boolean newSession = ss.getCurrentSessionTimes(TestUtils.parseLocalTimestamp(lastConnectionTimestamp));
// Assert.assertFalse("old session", newSession);
// }
private SimpleSessionSchedule makeSchedule (int startDayOfWeek, int endDayOfWeek, String startTimeOfDay, String endTimeOfDay, boolean isDailySchedule) {
return new SimpleSessionSchedule(startDayOfWeek, endDayOfWeek, startTimeOfDay, endTimeOfDay, isDailySchedule, null);
}
public static void test() {
SessionSchedule schedule = new SimpleSessionSchedule(Calendar.SUNDAY, Calendar.FRIDAY, "17:30:00", "17:00:00", true, TimeZone.getTimeZone("America/New_York"));
MessageStore messageStore = new InMemoryMessageStore(1 << 20);
FixSessionInitiator initiator = null;
initiator.setMessageStore(messageStore);
initiator.setSessionSchedule(schedule);
}
private static String formatDuration (long millis) {
int hours = (int) millis / 3600000;
int minutes = (int) (millis % 3600000) / 60000;
int seconds = (int) (millis % 60000) / 1000;
int msec = (int) millis % 1000;
return String.format("%02d:%02d:%02d.%03d", hours, minutes, seconds, msec);
}
}