// Copyright 2006 Google Inc. All Rights Reserved.
//
// 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 com.google.enterprise.connector.scheduler;
import junit.framework.TestCase;
import java.util.Calendar;
/**
* Test Schedule class.
*/
public class ScheduleTest extends TestCase {
private static final String strWithDelay = "connector1:60:0:1-2:3-5";
private static final String strWithDefaultDelay =
"connector1:60:300000:1-2:3-5";
private static final String strNoDelay = "connector1:60:1-2:3-5";
private static final String strIntervals = "1-2:3-5";
private static final String strWithDisabled = "#connector1:60:0:1-2:3-5";
private static final String strWithDelayNoIntervals = "connector2:60:0:";
private static final String strWithDefaultDelayNoIntervals =
"connector2:60:300000:";
private static final String strNoDelayNoIntervals = "connector2:60:";
private static final String[] illegalSchedules =
{"connector1", "connector2:60", "connector2:60:0", "connector1:60:0:1",
"connector1:xyx:0:1", "connector1:60:0:xyzzy",
"connector1:60:0:1-2:3", "connector1:60:0:1-2:3:"};
public void testStaticFactoryMethod() {
assertNull(Schedule.of(null));
assertNull(Schedule.of(""));
Schedule schedule = Schedule.of(strWithDelay);
assertNotNull(schedule);
assertEquals(schedule.toString(), strWithDelay, schedule.toString());
}
public void testStaticToString() {
String schedStr = Schedule.toString(null);
assertNotNull(schedStr);
assertTrue(schedStr, schedStr.startsWith("#"));
assertTrue(schedStr, schedStr.contains(":0-0"));
schedStr = Schedule.toString(Schedule.of(strWithDelay));
assertNotNull(schedStr);
assertEquals(schedStr, strWithDelay, schedStr);
}
public void testSerialization() {
Schedule schedule1 = new Schedule("connector1", false, 60, 0, strIntervals);
assertEquals(strWithDelay, schedule1.toString());
assertFalse(schedule1.isDisabled());
assertEquals(strIntervals, schedule1.getTimeIntervals());
assertEquals("connector1", schedule1.getConnectorName());
assertEquals(60, schedule1.getTraversalRate());
assertEquals(60, schedule1.getLoad());
assertEquals(0, schedule1.getRetryDelay());
Schedule schedule2 = new Schedule("whatever", false, 30, 42, strIntervals);
schedule2.readString(strWithDelay);
assertEquals(strWithDelay, schedule2.toString());
schedule2.readString(strNoDelay);
assertEquals(strWithDefaultDelay, schedule2.toString());
Schedule schedule3 = new Schedule(strWithDelay);
assertEquals(strWithDelay, schedule3.toString());
assertFalse(schedule3.isDisabled());
assertEquals(strIntervals, schedule3.getTimeIntervals());
assertEquals("connector1", schedule3.getConnectorName());
assertEquals(60, schedule3.getTraversalRate());
assertEquals(60, schedule3.getLoad());
assertEquals(0, schedule3.getRetryDelay());
// Missing delay becomes Default.
Schedule schedule4 = new Schedule(strNoDelay);
assertEquals(strWithDefaultDelay, schedule4.toString());
assertEquals(300, schedule4.getRetryDelay());
// Empty Schedules are now permitted.
Schedule schedule5 = new Schedule("connector2", false, 60, 0, null);
assertNotNull(schedule5.getTimeIntervals());
assertEquals("", schedule5.getTimeIntervals());
assertEquals(strWithDelayNoIntervals, schedule5.toString());
Schedule schedule5b = new Schedule("connector2", false, 60, 0, "");
assertNotNull(schedule5b.getTimeIntervals());
assertEquals("", schedule5b.getTimeIntervals());
assertEquals(strWithDelayNoIntervals, schedule5b.toString());
Schedule schedule5c = new Schedule(strWithDelayNoIntervals);
assertEquals(strWithDelayNoIntervals, schedule5c.toString());
Schedule schedule5d = new Schedule(strNoDelayNoIntervals);
assertEquals(strWithDefaultDelayNoIntervals, schedule5d.toString());
// Test Disabled Schedules.
Schedule schedule9 = new Schedule("connector1", true, 60, 0, strIntervals);
assertEquals(strWithDisabled, schedule9.toString());
assertTrue(schedule9.isDisabled());
assertFalse(schedule9.shouldRun());
Schedule schedule10 = new Schedule(strWithDisabled);
assertEquals(strWithDisabled, schedule10.toString());
assertTrue(schedule10.isDisabled());
assertFalse(schedule10.shouldRun());
for (String badSched : illegalSchedules) {
try {
new Schedule(badSched);
fail("IllegalArgumentException expected for invalid schedule \""
+ badSched + "\"");
} catch (IllegalArgumentException e) {
// Expected exception occurred.
assertEquals("Invalid schedule string format: \"" + badSched + "\"",
e.getMessage());
}
}
}
public void testToLegacyStringFromNull() {
// Legacy GSAs cannot handle null Schedules.
// But they also cannot handle disabled schedules or retry delay.
String schedStr = Schedule.toLegacyString(null);
assertNotNull(schedStr);
assertFalse(schedStr, schedStr.contains(":300000:"));
assertFalse(schedStr, schedStr.startsWith("#"));
assertTrue(schedStr, schedStr.contains(":0-0"));
}
public void testToLegacyString() {
// Identity should work.
assertEquals(strNoDelay, Schedule.toLegacyString(strNoDelay));
// Legacy format doesn't include delay.
assertEquals(strNoDelay, Schedule.toLegacyString(strWithDelay));
// Legacy format doesn't include disabled.
assertEquals(strNoDelay, Schedule.toLegacyString(strWithDisabled));
// Legacy format does support no time intervals.
assertEquals(strNoDelayNoIntervals,
Schedule.toLegacyString(strWithDelayNoIntervals));
assertEquals(strNoDelayNoIntervals,
Schedule.toLegacyString(strNoDelayNoIntervals));
// Invalid schedule strings should throw IllegalArgumentException.
for (String badSched : illegalSchedules) {
try {
Schedule.toLegacyString(badSched);
fail("IllegalArgumentException expected for invalid schedule \""
+ badSched + "\"");
} catch (IllegalArgumentException e) {
// Expected exception occurred.
assertEquals("Invalid schedule string format: \"" + badSched + "\"",
e.getMessage());
}
}
}
public void testGettersAndSetters() throws Exception {
// Test static setters/getters first.
int savedRetryDelay = Schedule.defaultRetryDelayMillis();
Schedule.setDefaultRetryDelaySecs(20);
assertEquals(20000, Schedule.defaultRetryDelayMillis());
Schedule.setDefaultRetryDelaySecs(savedRetryDelay / 1000);
// Now test the instance setters/getters.
Schedule schedule = new Schedule();
schedule.setConnectorName("connector1");
assertEquals("connector1", schedule.getConnectorName());
schedule.setDisabled(true);
assertTrue(schedule.isDisabled());
schedule.setDisabled(false);
assertFalse(schedule.isDisabled());
schedule.setLoad(2000);
assertEquals(2000, schedule.getLoad());
assertEquals(2000, schedule.getTraversalRate());
schedule.setRetryDelayMillis(30000);
assertEquals(30000, schedule.getRetryDelayMillis());
assertEquals(30, schedule.getRetryDelay());
schedule.setTimeIntervals(null);
assertEquals("", schedule.getTimeIntervals());
schedule.setTimeIntervals("");
assertEquals("", schedule.getTimeIntervals());
schedule.setTimeIntervals("0-0");
assertEquals("0-0", schedule.getTimeIntervals());
schedule.setTimeIntervals("0-4:8-14");
assertEquals("0-4:8-14", schedule.getTimeIntervals());
assertEquals("connector1:2000:30000:0-4:8-14", schedule.toString());
}
public void testNoIntervals() {
Schedule schedule = new Schedule(strWithDelayNoIntervals);
assertFalse(schedule.shouldRun());
assertFalse(schedule.inScheduledInterval());
assertEquals(-1, schedule.nextScheduledInterval());
assertEquals("", schedule.getTimeIntervals());
}
public void testAlwaysRun() {
Schedule schedule = new Schedule(strWithDelayNoIntervals + "0-0");
assertTrue(schedule.shouldRun());
assertTrue(schedule.inScheduledInterval());
assertEquals(0, schedule.nextScheduledInterval());
assertEquals("0-0", schedule.getTimeIntervals());
}
public void testNextScheduleInterval() throws Exception {
// No Schedule intervals.
testIntervals("", new int[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 });
// Legacy disabled schedule.
testIntervals("1-1", new int[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 });
// Always run.
testIntervals("0-0", new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
// Always run.
testIntervals("0-24", new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
// Only in the AM.
testIntervals("0-12", new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 });
// Only in the PM.
testIntervals("12-24", new int[] { 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
// Two 4 hour intervals.
int [] expected = new int[] { 4, 3, 2, 1, 0, 0, 0, 0, 8, 7, 6, 5,
4, 3, 2, 1, 0, 0, 0, 0, 8, 7, 6, 5 };
testIntervals("4-8:16-20", expected);
// Out of order intervals should have no impact.
testIntervals("16-20:4-8", expected);
// Increasing gaps between intervals.
testIntervals("0-1:2-3:5-6:9-10:14-15:20-21", new int[] { 0, 1, 0, 2, 1, 0,
3, 2, 1, 0, 4, 3, 2, 1, 0, 5, 4, 3, 2, 1, 0, 3, 2, 1 });
// Schedule interval wraps midnight.
testIntervals("18-8", new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 10, 9, 8, 7, 6,
5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0 });
// Schedule interval wraps midnight, and one that does not.
testIntervals("18-8:12-13", new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 2, 1,
0, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0 });
}
/**
* Tests number of hours until next traversal interval for each hour of the day.
*/
private void testIntervals(String intervals, int[] nextIntervalHours) {
Schedule schedule = new Schedule("name", false, 500, 60, intervals);
Calendar calendar = Calendar.getInstance();
// We only care about hours and minutes. Ignore date, seconds, millis, etc.
calendar.set(Calendar.MINUTE, 0);
for (int i = 0; i < 24; i++) {
calendar.set(Calendar.HOUR_OF_DAY, i);
int nextInterval = (nextIntervalHours[i] < 0) ? nextIntervalHours[i]
: nextIntervalHours[i] * 3600;
assertEquals("Hour = " + i, nextInterval,
schedule.nextScheduledInterval(calendar));
}
}
/** Test Fractions of an hour remaining until next traversal interval. */
public void testIntervalMinutes() {
Schedule schedule = new Schedule("name", false, 500, 60, "2-3");
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 1);
calendar.set(Calendar.MINUTE, 40);
assertEquals(20 * 60, schedule.nextScheduledInterval(calendar));
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 15);
assertEquals((60 + 45) * 60, schedule.nextScheduledInterval(calendar));
calendar.set(Calendar.HOUR_OF_DAY, 2);
calendar.set(Calendar.MINUTE, 50);
assertEquals(0, schedule.nextScheduledInterval(calendar));
calendar.set(Calendar.HOUR_OF_DAY, 20);
calendar.set(Calendar.MINUTE, 20);
assertEquals((((5 * 60) + 40) * 60),
schedule.nextScheduledInterval(calendar));
}
}