Package fm.last.citrine.scheduler

Source Code of fm.last.citrine.scheduler.SchedulerManagerTest

/*
* Copyright 2010 Last.fm
*
*  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 fm.last.citrine.scheduler;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.quartz.SchedulerException;
import org.springframework.test.annotation.DirtiesContext;

import fm.last.citrine.model.Status;
import fm.last.citrine.model.Task;
import fm.last.citrine.model.TaskRun;
import fm.last.citrine.service.TaskManager;
import fm.last.citrine.service.TaskRunManager;
import fm.last.test.BaseSpringTestCase;

/**
* Unit test case for the SchedulerManager.
*/
public class SchedulerManagerTest extends BaseSpringTestCase {

  private static Logger log = Logger.getLogger(SchedulerManagerTest.class);

  private static final String BEAN_WAIT_JOB = "waitJob";

  private static final int DEFAULT_TEST_TIMEOUT = 60000;

  @Resource
  private SchedulerManager schedulerManager;

  @Resource
  private TaskManager taskManager;

  @Resource
  private TaskRunManager taskRunManager;

  private String defaultTimerSchedule = "0 15 10 ? * 6L 3002-3005"; // a timer schedule string that should never run

  private String testGroup = "testGroup";

  // an enabled Task with stopOnError set to true that is guaranteed to fail
  private Task failTask = new Task("name", testGroup, "failTask", true, true, "true", "");

  /**
   * Cleaning up the tables also needs to happen *after* to prevent the scheduler from starting tasks before this test
   * runs.
   *
   * @throws SchedulerException
   * @throws InterruptedException
   */
  @Before
  @After
  public void cleanup() throws SchedulerException, InterruptedException {
    super.cleanupTaskTables();
  }

  /**
   * Utility method to give a Task a chance to finish running. Uses a preconfigured default number of attempts.
   *
   * @param task Task to wait for.
   * @throws InterruptedException If this Thread is interrupted while waiting.
   */
  private void waitForTask(Task task) throws InterruptedException {
    waitForTask(task, 20);
  }

  /**
   * Utility method to give a Task a chance to finish running. Uses a preconfigured default number of attempts.
   *
   * @param task Task to wait for.
   * @param maxAttempts Maximum number of times to wait for Task.
   * @throws InterruptedException If this Thread is interrupted while waiting.
   */
  private void waitForTask(Task task, int maxAttempts) throws InterruptedException {
    int attempts = 0;
    while (attempts < maxAttempts) {
      log.debug("Waiting for Task " + task.getId() + " (" + task.getName() + ")");
      Thread.sleep(3000); // give task time to run
      List<TaskRun> taskRuns = taskRunManager.findByTaskId(task.getId());
      if (taskRuns.size() == 0) { // task run hasn't even been created yet
        log.debug("No task runs found");
      } else {
        if (!taskRunManager.isRunning(task.getId())) {
          return; // no longer running, get outta here
        }
      }
      attempts++;
    }
  }

  /**
   * Tests running a task that fails due to invalid command.
   *
   * @throws InterruptedException
   */
  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testRunNow_InvalidCommand() throws InterruptedException {
    Task task = new Task("name", "groupName", "sysExecJob", false, true, "invalidcommand", defaultTimerSchedule);
    taskManager.save(task);
    schedulerManager.runTaskNow(task);
    waitForTask(task);
    List<TaskRun> taskRuns = taskRunManager.findByTaskId(task.getId());
    assertEquals(1, taskRuns.size());
    TaskRun taskRun = taskRuns.get(0);
    assertEquals(Status.FAILED, taskRun.getStatus());

    // only stack trace should be filled in
    assertNotNull(taskRun.getStackTrace());
    assertNull(taskRun.getSysOut());
    assertNull(taskRun.getSysErr());
  }

  /**
   * Tests running a task that runs, but its command generates an error.
   *
   * @throws InterruptedException
   */
  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testRunNow_FailureWhileRunning() throws InterruptedException {
    Task task = new Task("name", "groupName", "sysExecJob", false, true, "ls -l23frx", defaultTimerSchedule);
    taskManager.save(task);
    schedulerManager.runTaskNow(task);
    waitForTask(task);
    List<TaskRun> taskRuns = taskRunManager.findByTaskId(task.getId());
    assertEquals(1, taskRuns.size());
    TaskRun taskRun = taskRuns.get(0);
    assertEquals(Status.FAILED, taskRun.getStatus());

    // stack trace and sys err should be filled in
    assertNotNull(taskRun.getStackTrace());
    assertTrue(StringUtils.isEmpty(taskRun.getSysOut()));
    assertFalse("Expected a string but got '" + taskRun.getSysErr() + "'", StringUtils.isEmpty(taskRun.getSysErr()));
  }

  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testRunNow_Success() throws InterruptedException {
    Task task = new Task("name", "groupName", "sysExecJob", false, true, "sleep 5", defaultTimerSchedule);
    taskManager.save(task);
    schedulerManager.runTaskNow(task);
    Thread.sleep(1000); // give task time to get started
    assertTrue(taskRunManager.isRunning(task.getId()));
    waitForTask(task);
    assertFalse(taskRunManager.isRunning(task.getId()));
    List<TaskRun> taskRuns = taskRunManager.findByTaskId(task.getId());
    assertEquals(1, taskRuns.size());
    TaskRun taskRun = taskRuns.get(0);
    assertEquals(Status.SUCCESS, taskRun.getStatus());

    // we slept so there should be no output at all
    assertNull(taskRun.getStackTrace());
    assertTrue(StringUtils.isEmpty(taskRun.getSysOut()));
    assertTrue(StringUtils.isEmpty(taskRun.getSysErr()));
  }

  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testRunSameTaskSimultaneously() throws InterruptedException {
    Task task = new Task("name", "groupName", "sysExecJob", false, true, "sleep 5", defaultTimerSchedule);
    taskManager.save(task);
    schedulerManager.runTaskNow(task);
    Thread.sleep(1000); // give task time to get started
    assertTrue(taskRunManager.isRunning(task.getId()));

    try {
      schedulerManager.runTaskNow(task);
      fail("Should not be able to run the same task simultaneously");
    } catch (ScheduleException e) {
      // expected
    }

    waitForTask(task);
    assertFalse(taskRunManager.isRunning(task.getId()));
    List<TaskRun> taskRuns = taskRunManager.findByTaskId(task.getId());
    assertEquals(1, taskRuns.size());
    TaskRun taskRun = taskRuns.get(0);
    assertEquals(Status.SUCCESS, taskRun.getStatus());

    // now that task has finished, try run it again
    schedulerManager.runTaskNow(task);
    Thread.sleep(1000); // give task time to get started
    assertTrue(taskRunManager.isRunning(task.getId()));
    waitForTask(task);
    assertFalse(taskRunManager.isRunning(task.getId()));
    taskRuns = taskRunManager.findByTaskId(task.getId());
    assertEquals(2, taskRuns.size());
    assertEquals(Status.SUCCESS, taskRuns.get(0).getStatus());
    assertEquals(Status.SUCCESS, taskRuns.get(1).getStatus());
  }

  /**
   * Tests whether two instances of the task can be run at the same time, using via calls to runTaskNow(). Note that
   * this is different to a task being set to run while another job is running due to a cron trigger.
   *
   * @throws InterruptedException
   */
  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testRunNow_AbortOnRunning() throws InterruptedException {
    Task task = new Task("name", "groupName", "sysExecJob", false, true, "sleep 3", defaultTimerSchedule);
    taskManager.save(task);
    schedulerManager.runTaskNow(task);
    try { // try run task again, quartz should not allow this
      schedulerManager.runTaskNow(task);
    } catch (ScheduleException e) {
      // expected
    }
    waitForTask(task);
    List<TaskRun> taskRuns = taskRunManager.findByTaskId(task.getId());
    assertEquals(1, taskRuns.size());
    TaskRun taskRun = taskRuns.get(0); // most recent job run should be first in list, i.e. the one that aborted
    assertEquals(Status.SUCCESS, taskRun.getStatus());
    assertTrue(StringUtils.isEmpty(taskRun.getStackTrace()));
    assertTrue(StringUtils.isEmpty(taskRun.getSysOut()));
    assertTrue(StringUtils.isEmpty(taskRun.getSysErr()));
  }

  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testRunNow_Success_WithChild() throws InterruptedException {
    Task task1 = new Task("name", "groupName", "sysExecJob", false, true, "ls", defaultTimerSchedule);
    taskManager.save(task1);
    Task task2 = new Task("name2", "groupName", "sysExecJob", true, true, "ls", "");
    taskManager.save(task2);
    task1.addChildTask(task2);
    taskManager.save(task1);

    schedulerManager.runTaskNow(task1);
    waitForTask(task2);

    List<TaskRun> taskRuns = taskRunManager.findByTaskId(task1.getId());
    assertEquals(1, taskRuns.size());
    TaskRun taskRun = taskRuns.get(0);
    assertEquals(Status.SUCCESS, taskRun.getStatus());

    taskRuns = taskRunManager.findByTaskId(task2.getId());
    assertEquals(1, taskRuns.size());
    taskRun = taskRuns.get(0);
    assertEquals(Status.SUCCESS, taskRun.getStatus());
  }

  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testRunNow_Failure_WithChild_StopOnErrorTrue() throws InterruptedException {
    failTask.setStopOnError(true);
    taskManager.save(failTask);
    Task task2 = new Task("name2", "groupName", "sysExecJob", true, true, "ls", "");
    taskManager.save(task2);
    failTask.addChildTask(task2);
    taskManager.save(failTask);

    schedulerManager.runTaskNow(failTask);
    waitForTask(failTask);

    Thread.sleep(1000);

    List<TaskRun> taskRuns = taskRunManager.findByTaskId(failTask.getId());
    assertEquals(1, taskRuns.size());
    TaskRun jobRun = taskRuns.get(0);
    assertEquals(Status.FAILED, jobRun.getStatus());

    assertEquals(0, taskRunManager.findByTaskId(task2.getId()).size());
  }

  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testRunNow_Failure_WithChild_StopOnErrorFalse() throws InterruptedException {
    // set stopOnError for parent to false, child should run even though parent fails
    failTask.setStopOnError(false);
    taskManager.save(failTask);
    Task task2 = new Task("name2", "groupName", "sysExecJob", true, true, "ls", "");
    taskManager.save(task2);
    failTask.addChildTask(task2);
    taskManager.save(failTask);

    schedulerManager.runTaskNow(failTask);
    waitForTask(task2); // job2 should run even though failJob fails

    List<TaskRun> taskRuns = taskRunManager.findByTaskId(failTask.getId());
    assertEquals(1, taskRuns.size());
    TaskRun taskRun = taskRuns.get(0);
    assertEquals(Status.FAILED, taskRun.getStatus());

    assertEquals(1, taskRunManager.findByTaskId(task2.getId()).size());
  }

  /**
   * Tests running a task "diamond" where job 1 has children 2,3 and they both have child 4.
   *
   * @throws InterruptedException
   */
  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testRunNow_ChildDiamond() throws InterruptedException {
    Task task1 = new Task("name", "groupName", "sysExecJob", false, true, "ls", defaultTimerSchedule);
    taskManager.save(task1);
    Task task2 = new Task("name2", "groupName", "sysExecJob", false, true, "ls", "");
    taskManager.save(task2);
    task1.addChildTask(task2);
    taskManager.save(task1);

    schedulerManager.runTaskNow(task1);
    waitForTask(task1);

    List<TaskRun> taskRuns = taskRunManager.findByTaskId(task1.getId());
    assertEquals(1, taskRuns.size());
    TaskRun taskRun = taskRuns.get(0);
    assertEquals(Status.SUCCESS, taskRun.getStatus());

    // wait once for task2 just to make sure it hasn't actually run
    waitForTask(task2, 1);

    // task 2 is disabled, so even though it is child of 1, it should not run
    taskRuns = taskRunManager.findByTaskId(task2.getId());
    assertEquals(0, taskRuns.size());
  }

  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testChildStillRunning() throws InterruptedException {
    Task parentTask = new Task("parent", "groupName", "sysExecJob", false, true, "ls", defaultTimerSchedule);
    taskManager.save(parentTask);
    Task childTask = new Task("child", "groupName", "sysExecJob", true, true, "sleep 10", "");
    taskManager.save(childTask);
    parentTask.addChildTask(childTask);
    taskManager.save(parentTask);

    schedulerManager.runTaskNow(parentTask);
    waitForTask(parentTask);
    Thread.sleep(1000); // give task 2 a chance to get going
    assertTrue(taskRunManager.isRunning(childTask.getId()));

    schedulerManager.runTaskNow(parentTask); // now run task 1 again
    waitForTask(parentTask);
    waitForTask(childTask);

    // now run 1 again, should all go fine
    schedulerManager.runTaskNow(parentTask);
    waitForTask(childTask);

    List<TaskRun> parentTaskRuns = taskRunManager.findByTaskId(parentTask.getId());
    assertEquals(3, parentTaskRuns.size());
    assertEquals(Status.SUCCESS, parentTaskRuns.get(0).getStatus());
    assertEquals(Status.SUCCESS, parentTaskRuns.get(1).getStatus());
    assertEquals(Status.SUCCESS, parentTaskRuns.get(2).getStatus());

    List<TaskRun> childTaskRuns = taskRunManager.findByTaskId(childTask.getId());
    assertEquals(3, childTaskRuns.size());
    assertEquals(Status.SUCCESS, childTaskRuns.get(0).getStatus());
    assertEquals(Status.ABORTED, childTaskRuns.get(1).getStatus());
    assertEquals(Status.SUCCESS, childTaskRuns.get(2).getStatus());
  }

  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testRunNow_Success_WithChildDisabled() throws InterruptedException {
    String group = "diamondTest";
    Task task1 = new Task("task1", group, BEAN_WAIT_JOB, true, true, "3000", "");
    taskManager.save(task1);
    Task task2 = new Task("task2", group, BEAN_WAIT_JOB, true, true, "100", "");
    taskManager.save(task2);
    Task task3 = new Task("task3", group, BEAN_WAIT_JOB, true, true, "6000", "");
    taskManager.save(task3);
    Task task4 = new Task("task4", group, BEAN_WAIT_JOB, true, true, "1000", "");
    taskManager.save(task4);

    // now create our task "diamond"
    task1.addChildTask(task2);
    task1.addChildTask(task3);
    taskManager.save(task1);
    task2.addChildTask(task4);
    taskManager.save(task2);
    task3.addChildTask(task4);
    taskManager.save(task3);

    schedulerManager.runTaskNow(task1);
    Thread.sleep(1000); // wait enough that task1 should have started but not yet finished
    assertEquals(1, taskRunManager.findByTaskId(task1.getId()).size());
    assertEquals(0, taskRunManager.findByTaskId(task3.getId()).size());
    assertEquals(0, taskRunManager.findByTaskId(task2.getId()).size());

    waitForTask(task1);
    // now tasks 2 and 3 should get kicked off
    Thread.sleep(1000); // wait a bit for this to happen
    assertEquals(1, taskRunManager.findByTaskId(task2.getId()).size());
    assertEquals(1, taskRunManager.findByTaskId(task3.getId()).size());
    assertEquals(0, taskRunManager.findByTaskId(task4.getId()).size()); // should not be triggered yet

    waitForTask(task4); // once 2 and 3 are finished, 4 should get triggered
    assertEquals(1, taskRunManager.findByTaskId(task1.getId()).size());
    assertEquals(1, taskRunManager.findByTaskId(task2.getId()).size());
    assertEquals(1, taskRunManager.findByTaskId(task3.getId()).size());
    assertEquals(1, taskRunManager.findByTaskId(task4.getId()).size());
  }

  /**
   * Tests running the diamond, where task 2 fails, 3 succeeds, due to "AND" nature of stopOnError, task 4 should still
   * run.
   *
   * @throws InterruptedException
   */
  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testRunNow_ChildDiamond_StopOnError_2Fails() throws InterruptedException {
    String group = "diamondTest";
    Task task1 = new Task("task1", group, BEAN_WAIT_JOB, true, true, "3000", "");
    taskManager.save(task1);
    // set task 2 to fail
    Task task2 = new Task("task2", group, "failJob", true, true, "true", "");
    taskManager.save(task2);
    Task task3 = new Task("task3", group, BEAN_WAIT_JOB, true, true, "5000", "");
    taskManager.save(task3);
    Task task4 = new Task("task4", group, BEAN_WAIT_JOB, true, true, "1000", "");
    taskManager.save(task4);

    // now create our task "diamond"
    task1.addChildTask(task2);
    task1.addChildTask(task3);
    taskManager.save(task1);
    task2.addChildTask(task4);
    taskManager.save(task2);
    task3.addChildTask(task4);
    taskManager.save(task3);

    schedulerManager.runTaskNow(task1);
    waitForTask(task4); // task 4 should run

    List<TaskRun> taskRuns = taskRunManager.findByTaskId(task2.getId());
    assertEquals(1, taskRuns.size());
    TaskRun taskRun = taskRuns.get(0);
    assertEquals(Status.FAILED, taskRun.getStatus());

    taskRuns = taskRunManager.findByTaskId(task4.getId());
    assertEquals(1, taskRuns.size());
    taskRun = taskRuns.get(0);
    assertEquals(Status.SUCCESS, taskRun.getStatus());
  }

  /**
   * Tests running the diamond, where task 2 and 3 failsdue to "AND" nature of stopOnError, task 4 should not run.
   *
   * @throws InterruptedException
   */
  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testRunNow_ChildDiamond_StopOnError_2And3Fail() throws InterruptedException {
    String group = "diamondTest";
    Task task1 = new Task("task1", group, BEAN_WAIT_JOB, true, true, "3000", "");
    taskManager.save(task1);
    // set tasks 2 and 3 to fail
    Task task2 = new Task("task2", group, "failJob", true, true, "true", "");
    taskManager.save(task2);
    Task task3 = new Task("task3", group, "failJob", true, true, "true", "");
    taskManager.save(task3);
    Task task4 = new Task("task4", group, BEAN_WAIT_JOB, true, true, "1000", "");
    taskManager.save(task4);

    // now create our task "diamond"
    task1.addChildTask(task2);
    task1.addChildTask(task3);
    taskManager.save(task1);
    task2.addChildTask(task4);
    taskManager.save(task2);
    task3.addChildTask(task4);
    taskManager.save(task3);

    schedulerManager.runTaskNow(task1);
    waitForTask(task2);
    waitForTask(task3);

    assertEquals(0, taskRunManager.findByTaskId(100).size());
  }

  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testStopTaskRun() throws InterruptedException {
    Task task = new Task("name", "groupName", "sysExecJob", false, true, "sleep 15", defaultTimerSchedule);
    taskManager.save(task);
    schedulerManager.runTaskNow(task);
    Thread.sleep(1000); // give job time to get started
    long taskRunId = taskRunManager.getMostRecent(task.getId()).getId();
    assertTrue(taskRunManager.isRunning(task.getId()));

    taskRunManager.stop(taskRunId);
    Thread.sleep(1000); // give job time to die
    assertFalse(taskRunManager.isRunning(task.getId()));
    List<TaskRun> taskRuns = taskRunManager.findByTaskId(task.getId());
    assertEquals(1, taskRuns.size());
    TaskRun taskRun = taskRuns.get(0);
    assertEquals(Status.CANCELLED, taskRun.getStatus());

    assertNotNull(taskRun.getStackTrace());
    assertTrue(StringUtils.isEmpty(taskRun.getSysOut()));
    assertTrue(StringUtils.isEmpty(taskRun.getSysErr()));
  }

  /**
   * Test that scheduling a task to run using a cron trigger works.
   */
  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testTimedScheduledRun() throws InterruptedException {
    Task task = new Task("testTimerScheduledRun", "groupName", "sysExecJob");
    task.setErrorIfRunning(true);
    task.setCommand("sleep 1");
    task.setTimerSchedule("*/10 * * * * ?");
    taskManager.save(task);
    waitForTask(task);

    List<TaskRun> taskRuns = taskRunManager.findByTaskId(task.getId());
    assertEquals(1, taskRuns.size());
    TaskRun taskRun = taskRuns.get(0);
    assertEquals(Status.SUCCESS, taskRun.getStatus());
  }

  /**
   * Test scheduling a task that will run for long enough that other runs are triggered while it is running. The task is
   * set to error if running, so the other runs should show up as aborted.
   */
  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  @DirtiesContext
  public void testTaskConflict_ErrorIfRunningTrue() throws InterruptedException {
    Task task = new Task("errorIfRunningTask", "groupName", "sysExecJob");
    task.setErrorIfRunning(true);
    task.setCommand("sleep 10");
    task.setTimerSchedule("*/3 * * * * ?");
    taskManager.save(task);
    waitForTask(task);

    List<TaskRun> taskRuns = taskRunManager.findByTaskId(task.getId());
    assertTrue(taskRuns.size() >= 3); // should be at least 1 success run and two aborted
    int successCount = 0;
    int abortCount = 0;
    for (TaskRun taskRun : taskRuns) {
      // there might be more than 1 successful run depending on timing above, all others should be aborted
      if (Status.SUCCESS.equals(taskRun.getStatus())) {
        successCount++;
      } else if (Status.ABORTED.equals(taskRun.getStatus())) {
        abortCount++;
      }
    }
    assertTrue(abortCount > successCount); // should be more runs aborted while task ran successfully
  }

  /**
   * Test scheduling a task that will run for long enough that other runs are triggered while it is running. The task is
   * set NOT to error if running, so the other runs should not show up in task runs table at all.
   */
  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  @DirtiesContext
  public void testTaskConflict_ErrorIfRunningFalse() throws InterruptedException {
    Task task = new Task("noErrorIfRunningTask", "groupName", "sysExecJob");
    task.setErrorIfRunning(false);
    task.setCommand("sleep 10");
    task.setTimerSchedule("*/3 * * * * ?");
    taskManager.save(task);
    waitForTask(task);

    List<TaskRun> taskRuns = taskRunManager.findByTaskId(task.getId());
    assertTrue(taskRuns.size() >= 1); // should be at least 1 run, maybe more depending on timing
    for (TaskRun taskRun : taskRuns) { // all runs should be marked as success (all aborts ignored)
      assertEquals(Status.SUCCESS, taskRun.getStatus());
    }
  }

  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  public void testGetCurrentlyRunningTaskIds() throws InterruptedException, SchedulerException {
    Task task = new Task("name", "groupName", "sysExecJob", false, true, "sleep 5", defaultTimerSchedule);
    taskManager.save(task);
    assertEquals(0, schedulerManager.getCurrentlyRunningTaskIds().size());
    schedulerManager.runTaskNow(task);
    Thread.sleep(1000); // give task time to get started
    assertTrue(taskRunManager.isRunning(task.getId()));
    List<Long> taskIds = schedulerManager.getCurrentlyRunningTaskIds();
    assertEquals(1, taskIds.size());
    assertEquals(task.getId(), (long) taskIds.get(0));
    waitForTask(task);
    assertEquals(0, schedulerManager.getCurrentlyRunningTaskIds().size());
  }

  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  @DirtiesContext
  public void testReset() throws InterruptedException {
    Task task = new Task("testReset", "groupName", "sysExecJob");
    task.setErrorIfRunning(true);
    task.setCommand("sleep 1");
    task.setTimerSchedule("*/10 * * * * ?");
    taskManager.save(task); // save triggers schedule
    waitForTask(task);

    List<TaskRun> taskRuns = taskRunManager.findByTaskId(task.getId());
    int runCount = taskRuns.size();
    assertTrue(runCount >= 1); // in most cases will be 1, but might get triggered again before we get here
    TaskRun taskRun = taskRuns.get(0);
    assertEquals(Status.SUCCESS, taskRun.getStatus());

    schedulerManager.resetTask(task); // this will delete the job and reschedule it
    Thread.sleep(5000); // wait for job to run at least one more time to check reschedule worked
    waitForTask(task);

    taskRuns = taskRunManager.findByTaskId(task.getId());
    assertTrue(taskRuns.size() > runCount); // should have run at least one more time
  }

  @Test(timeout = DEFAULT_TEST_TIMEOUT)
  @DirtiesContext
  public void testPrepareForShutdown() throws InterruptedException {
    assertEquals(SchedulerStatus.STARTED, schedulerManager.getStatus());
    Task task = new Task("name", "groupName", "sysExecJob", false, true, "sleep 5", defaultTimerSchedule);
    taskManager.save(task);
    schedulerManager.runTaskNow(task);
    Thread.sleep(1000); // give task time to get started
    assertTrue(taskRunManager.isRunning(task.getId()));
    schedulerManager.prepareForShutdown();
    // task is still running, so should still be in "preparing for shutdown" mode
    assertEquals(SchedulerStatus.PREPARING_FOR_SHUTDOWN, schedulerManager.getStatus());
    waitForTask(task);
    // task no longer running, ready
    assertEquals(SchedulerStatus.READY_FOR_SHUTDOWN, schedulerManager.getStatus());
    schedulerManager.runTaskNow(task);
    Thread.sleep(1000); // give task time to get started
    assertFalse(taskRunManager.isRunning(task.getId())); // scheduler should not run anything anymore
    assertEquals(SchedulerStatus.READY_FOR_SHUTDOWN, schedulerManager.getStatus());
    schedulerManager.shutdown();
    assertEquals(SchedulerStatus.SHUTDOWN, schedulerManager.getStatus());
  }

}
TOP

Related Classes of fm.last.citrine.scheduler.SchedulerManagerTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.