@Test
  public void testPopulateJobConfig() throws Exception {
    IJobConfiguration job = IJobConfiguration.build(makeJob());
    SanitizedConfiguration sanitized =
        SanitizedConfiguration.fromUnsanitized(TaskTestUtil.CONFIGURATION_MANAGER, job);
    control.replay();

    Response response = assertOkResponse(thrift.populateJobConfig(job.newBuilder()));
    assertEquals(
        Result.populateJobResult(
            new PopulateJobResult(sanitized.getJobConfig().getTaskConfig().newBuilder())),
        response.getResult());
  }
  @Test
  public void testUpdate() throws Exception {
    SanitizedConfiguration updated =
        new SanitizedConfiguration(
            IJobConfiguration.build(job.newBuilder().setCronSchedule("1 2 3 4 5")));

    expectJobAccepted();
    cronScheduler.deschedule(DEFAULT_JOB_KEY);
    expectJobAccepted(updated.getJobConfig());

    control.replay();

    cron.receiveJob(sanitizedConfiguration);
    cron.updateJob(updated);
  }
  @Override
  public void validateJobResources(SanitizedConfiguration sanitizedConfiguration)
      throws ScheduleException {

    IJobConfiguration job = sanitizedConfiguration.getJobConfig();
    validateTaskLimits(job.getTaskConfig(), job.getInstanceCount());
  }
  @Test
  public void testDelayedStart() throws Exception {
    expectJobAccepted();
    expectJobFetch();

    // Query to test if live tasks exist for the job.
    expectActiveTaskFetch(TASK);

    // Live tasks exist, so the cron manager must delay the cron launch.
    delayExecutor.execute(capture(delayLaunchCapture));

    // The cron manager will then try to initiate the kill.
    scheduler.killTasks((Query.Builder) anyObject(), eq(CronJobManager.CRON_USER));

    // Immediate query and delayed query.
    expectActiveTaskFetch(TASK).times(2);

    // Simulate the live task disappearing.
    expectActiveTaskFetch();

    stateManager.insertPendingTasks(sanitizedConfiguration.getTaskConfigs());

    control.replay();

    cron.receiveJob(sanitizedConfiguration);
    cron.startJobNow(job.getKey());
    assertEquals(ImmutableSet.of(job.getKey()), cron.getPendingRuns());
    delayLaunchCapture.getValue().run();
    assertEquals(ImmutableSet.<IJobKey>of(), cron.getPendingRuns());
  }
  @Test(expected = ScheduleException.class)
  public void testScheduleFails() throws Exception {
    expectJobValidated(job);
    storageUtil.jobStore.saveAcceptedJob(MANAGER_KEY, sanitizedConfiguration.getJobConfig());
    expect(cronScheduler.schedule(eq(job.getCronSchedule()), EasyMock.<Runnable>anyObject()))
        .andThrow(new CronException("injected"));

    control.replay();

    cron.receiveJob(sanitizedConfiguration);
  }
  @Test
  public void testDeleteInconsistent() throws Exception {
    // Tests a case where a job exists in the storage, but is not registered with the cron system.

    expect(storageUtil.jobStore.fetchJob(MANAGER_KEY, job.getKey()))
        .andReturn(Optional.of(sanitizedConfiguration.getJobConfig()));

    control.replay();

    assertTrue(cron.deleteJob(job.getKey()));
  }
  @Before
  public void setUp() throws Exception {
    scheduler = createMock(SchedulerCore.class);
    stateManager = createMock(StateManager.class);
    delayExecutor = createMock(Executor.class);
    delayLaunchCapture = createCapture();
    storageUtil = new StorageTestUtil(this);
    storageUtil.expectOperations();
    cronScheduler = createMock(CronScheduler.class);
    shutdownRegistry = createMock(ShutdownRegistry.class);

    cron =
        new CronJobManager(
            stateManager, storageUtil.storage, cronScheduler, shutdownRegistry, delayExecutor);
    cron.schedulerCore = scheduler;
    job = makeJob();
    sanitizedConfiguration = SanitizedConfiguration.fromUnsanitized(job);
  }
  @Test
  public void testDelayedStartResets() throws Exception {
    expectJobAccepted();
    expectJobFetch();

    // Query to test if live tasks exist for the job.
    expectActiveTaskFetch(TASK);

    // Live tasks exist, so the cron manager must delay the cron launch.
    delayExecutor.execute(capture(delayLaunchCapture));

    // The cron manager will then try to initiate the kill.
    scheduler.killTasks((Query.Builder) anyObject(), eq(CronJobManager.CRON_USER));

    // Immediate query and delayed query.
    expectActiveTaskFetch(TASK).times(2);

    // Simulate the live task disappearing.
    expectActiveTaskFetch();

    // Round two.
    expectJobFetch();
    expectActiveTaskFetch(TASK);
    delayExecutor.execute(capture(delayLaunchCapture));
    scheduler.killTasks((Query.Builder) anyObject(), eq(CronJobManager.CRON_USER));
    expectActiveTaskFetch(TASK).times(2);
    expectActiveTaskFetch();

    stateManager.insertPendingTasks(sanitizedConfiguration.getTaskConfigs());
    expectLastCall().times(2);

    control.replay();

    cron.receiveJob(sanitizedConfiguration);
    cron.startJobNow(job.getKey());
    delayLaunchCapture.getValue().run();

    // Start the job again.  Since the previous delayed start completed, this should repeat the
    // entire process.
    cron.startJobNow(job.getKey());
    delayLaunchCapture.getValue().run();
  }
  @Test
  public void testStart() throws Exception {
    expectJobAccepted();
    expectJobFetch();
    expectActiveTaskFetch();

    // Job is executed immediately since there are no existing tasks to kill.
    stateManager.insertPendingTasks(sanitizedConfiguration.getTaskConfigs());
    expect(cronScheduler.getSchedule(DEFAULT_JOB_KEY))
        .andReturn(Optional.of(job.getCronSchedule()))
        .times(2);

    control.replay();

    assertEquals(ImmutableMap.<IJobKey, String>of(), cron.getScheduledJobs());
    cron.receiveJob(sanitizedConfiguration);
    assertEquals(ImmutableMap.of(job.getKey(), job.getCronSchedule()), cron.getScheduledJobs());
    cron.startJobNow(job.getKey());
    assertEquals(ImmutableMap.of(job.getKey(), job.getCronSchedule()), cron.getScheduledJobs());
  }
  @Test
  public void testDelayedStartMultiple() throws Exception {
    expectJobAccepted();
    expectJobFetch();

    // Query to test if live tasks exist for the job.
    expectActiveTaskFetch(TASK).times(3);

    // Live tasks exist, so the cron manager must delay the cron launch.
    delayExecutor.execute(capture(delayLaunchCapture));

    // The cron manager will then try to initiate the kill.
    expectJobFetch();
    expectJobFetch();
    scheduler.killTasks((Query.Builder) anyObject(), eq(CronJobManager.CRON_USER));
    expectLastCall().times(3);

    // Immediate queries and delayed query.
    expectActiveTaskFetch(TASK).times(4);

    // Simulate the live task disappearing.
    expectActiveTaskFetch();

    stateManager.insertPendingTasks(sanitizedConfiguration.getTaskConfigs());

    control.replay();

    cron.receiveJob(sanitizedConfiguration);

    // Attempt to trick the cron manager into launching multiple times, or launching multiple
    // pollers.
    cron.startJobNow(job.getKey());
    cron.startJobNow(job.getKey());
    cron.startJobNow(job.getKey());
    delayLaunchCapture.getValue().run();
  }
 private void expectJobFetch() {
   expectJobValidated();
   expect(storageUtil.jobStore.fetchJob(MANAGER_KEY, job.getKey()))
       .andReturn(Optional.of(sanitizedConfiguration.getJobConfig()));
 }
 private void expectJobAccepted() throws Exception {
   expectJobAccepted(sanitizedConfiguration.getJobConfig());
 }
 private void expectJobValidated() {
   expectJobValidated(sanitizedConfiguration.getJobConfig());
 }