/* * ProActive Parallel Suite(TM): * The Open Source library for parallel and distributed * Workflows & Scheduling, Orchestration, Cloud Automation * and Big Data Analysis on Enterprise Grids & Clouds. * * Copyright (c) 2007 - 2017 ActiveEon * Contact: contact@activeeon.com * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation: version 3 of * the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * If needed, contact us to obtain a release under GPL Version 2 or 3 * or a different license than the AGPL. */ package org.ow2.proactive.scheduler.core; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.eq; import java.util.Vector; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.ow2.proactive.scheduler.common.SchedulerEvent; import org.ow2.proactive.scheduler.common.job.JobId; import org.ow2.proactive.scheduler.common.job.JobInfo; import org.ow2.proactive.scheduler.common.job.JobPriority; import org.ow2.proactive.scheduler.common.task.OnTaskError; import org.ow2.proactive.scheduler.core.db.RecoveredSchedulerState; import org.ow2.proactive.scheduler.core.db.SchedulerDBManager; import org.ow2.proactive.scheduler.core.rmproxies.RMProxiesManager; import org.ow2.proactive.scheduler.job.InternalJob; import org.ow2.proactive.scheduler.job.InternalTaskFlowJob; import org.ow2.proactive.scheduler.job.JobIdImpl; import org.ow2.proactive.scheduler.job.JobInfoImpl; import org.ow2.proactive.scheduler.policy.DefaultPolicy; import org.ow2.proactive.scheduler.task.internal.InternalScriptTask; import org.ow2.proactive.scheduler.task.internal.InternalTask; public class SchedulingServiceTest { private SchedulingService schedulingService; @Mock private SchedulingInfrastructure infrastructure; @Mock private SchedulerStateUpdate listener; @Mock private RecoveredSchedulerState recoveredState; @Mock private SchedulingMethod schedulingMethod; @Mock private RMProxiesManager rmProxiesManager; @Mock private SchedulerDBManager schedulerDBManager; private final String policyClassName = DefaultPolicy.class.getName(); @Before public void init() throws Exception { MockitoAnnotations.initMocks(this); Mockito.when(recoveredState.getPendingJobs()).thenReturn(new Vector<InternalJob>()); Mockito.when(recoveredState.getRunningJobs()).thenReturn(new Vector<InternalJob>()); Mockito.when(recoveredState.getFinishedJobs()).thenReturn(new Vector<InternalJob>()); Mockito.when(infrastructure.getRMProxiesManager()).thenReturn(rmProxiesManager); Mockito.when(infrastructure.getDBManager()).thenReturn(schedulerDBManager); Mockito.when(rmProxiesManager.getRmUrl()).thenReturn(null); schedulingService = new SchedulingService(infrastructure, listener, recoveredState, policyClassName, schedulingMethod); } @Test public void testConstructorAndStart() { assertThat(schedulingService.status, is(schedulingService.status.STARTED)); } @Test public void testGetPolicy() { assertThat(schedulingService.getPolicy().getClass().getName(), is(policyClassName)); } @Test public void testIsSubmitPossible() { assertThat(schedulingService.isSubmitPossible(), is(true)); } @Test public void testIsNotSubmitPossible() { schedulingService.status = schedulingService.status.KILLED; assertThat(schedulingService.isSubmitPossible(), is(false)); schedulingService.status = schedulingService.status.STOPPED; assertThat(schedulingService.isSubmitPossible(), is(false)); schedulingService.status = schedulingService.status.SHUTTING_DOWN; assertThat(schedulingService.isSubmitPossible(), is(false)); schedulingService.status = schedulingService.status.DB_DOWN; assertThat(schedulingService.isSubmitPossible(), is(false)); } @Test public void testStop() { assertThat(schedulingService.stop(), is(true)); assertThat(schedulingService.status, is(schedulingService.status.STOPPED)); } @Test public void testCannotStop() { schedulingService.status = schedulingService.status.STOPPED; assertThat(schedulingService.stop(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.STOPPED)); schedulingService.status = schedulingService.status.UNLINKED; assertThat(schedulingService.stop(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.UNLINKED)); schedulingService.status = schedulingService.status.SHUTTING_DOWN; assertThat(schedulingService.stop(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.SHUTTING_DOWN)); schedulingService.status = schedulingService.status.KILLED; assertThat(schedulingService.stop(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.KILLED)); schedulingService.status = schedulingService.status.DB_DOWN; assertThat(schedulingService.stop(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.DB_DOWN)); } @Test public void testPause() { assertThat(schedulingService.pause(), is(true)); assertThat(schedulingService.status, is(schedulingService.status.PAUSED)); schedulingService.status = schedulingService.status.FROZEN; assertThat(schedulingService.pause(), is(true)); assertThat(schedulingService.status, is(schedulingService.status.PAUSED)); } @Test public void testCannotPause() { schedulingService.status = schedulingService.status.UNLINKED; assertThat(schedulingService.pause(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.UNLINKED)); schedulingService.status = schedulingService.status.SHUTTING_DOWN; assertThat(schedulingService.pause(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.SHUTTING_DOWN)); schedulingService.status = schedulingService.status.KILLED; assertThat(schedulingService.pause(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.KILLED)); schedulingService.status = schedulingService.status.DB_DOWN; assertThat(schedulingService.pause(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.DB_DOWN)); } @Test public void testFreeze() { assertThat(schedulingService.freeze(), is(true)); assertThat(schedulingService.status, is(schedulingService.status.FROZEN)); schedulingService.status = schedulingService.status.PAUSED; assertThat(schedulingService.freeze(), is(true)); assertThat(schedulingService.status, is(schedulingService.status.FROZEN)); } @Test public void testCannotFreeze() { schedulingService.status = schedulingService.status.UNLINKED; assertThat(schedulingService.freeze(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.UNLINKED)); schedulingService.status = schedulingService.status.SHUTTING_DOWN; assertThat(schedulingService.freeze(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.SHUTTING_DOWN)); schedulingService.status = schedulingService.status.KILLED; assertThat(schedulingService.freeze(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.KILLED)); schedulingService.status = schedulingService.status.DB_DOWN; assertThat(schedulingService.freeze(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.DB_DOWN)); } @Test public void testResume() { schedulingService.status = schedulingService.status.FROZEN; assertThat(schedulingService.resume(), is(true)); assertThat(schedulingService.status, is(schedulingService.status.STARTED)); schedulingService.status = schedulingService.status.PAUSED; assertThat(schedulingService.resume(), is(true)); assertThat(schedulingService.status, is(schedulingService.status.STARTED)); } @Test public void testCannotResume() { schedulingService.status = schedulingService.status.STARTED; assertThat(schedulingService.resume(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.STARTED)); schedulingService.status = schedulingService.status.SHUTTING_DOWN; assertThat(schedulingService.resume(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.SHUTTING_DOWN)); schedulingService.status = schedulingService.status.KILLED; assertThat(schedulingService.resume(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.KILLED)); schedulingService.status = schedulingService.status.DB_DOWN; assertThat(schedulingService.resume(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.DB_DOWN)); } @Test public void testShutdown() { schedulingService.status = schedulingService.status.STARTED; assertThat(schedulingService.shutdown(), is(true)); assertThat(schedulingService.status, is(schedulingService.status.SHUTTING_DOWN)); Mockito.verify(infrastructure, Mockito.times(1)).schedule(any(Runnable.class), org.mockito.Matchers.anyLong()); } @Test public void testCannotShutdown() { schedulingService.status = schedulingService.status.UNLINKED; assertThat(schedulingService.shutdown(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.UNLINKED)); schedulingService.status = schedulingService.status.SHUTTING_DOWN; assertThat(schedulingService.shutdown(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.SHUTTING_DOWN)); schedulingService.status = schedulingService.status.KILLED; assertThat(schedulingService.shutdown(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.KILLED)); schedulingService.status = schedulingService.status.DB_DOWN; assertThat(schedulingService.shutdown(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.DB_DOWN)); } @Test public void testKill() { schedulingService.status = schedulingService.status.STARTED; assertThat(schedulingService.kill(), is(true)); assertThat(schedulingService.status, is(schedulingService.status.KILLED)); Mockito.verify(infrastructure, Mockito.times(1)).shutdown(); Mockito.verify(listener, Mockito.times(1)).schedulerStateUpdated(SchedulerEvent.KILLED); } @Test public void testCannotKill() { schedulingService.status = schedulingService.status.KILLED; assertThat(schedulingService.kill(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.KILLED)); schedulingService.status = schedulingService.status.DB_DOWN; assertThat(schedulingService.kill(), is(false)); assertThat(schedulingService.status, is(schedulingService.status.DB_DOWN)); } @Test public void testCannotRestartTaskOnNodeFailure() { InternalJob job = new InternalTaskFlowJob("test-name", JobPriority.NORMAL, OnTaskError.CANCEL_JOB, "description"); schedulingService.status = schedulingService.status.KILLED; InternalTask task = new InternalScriptTask(job); schedulingService.restartTaskOnNodeFailure(task); Mockito.verify(infrastructure, Mockito.times(0)).getInternalOperationsThreadPool(); } @Test public void testRestartTaskOnNodeFailure() { InternalJob job = new InternalTaskFlowJob("test-name", JobPriority.NORMAL, OnTaskError.CANCEL_JOB, "description"); InternalTask task = new InternalScriptTask(job); ExecutorService executorService = Mockito.mock(ExecutorService.class); Mockito.when(infrastructure.getInternalOperationsThreadPool()).thenReturn(executorService); schedulingService.restartTaskOnNodeFailure(task); Mockito.verify(executorService, Mockito.times(1)).submit(any(Runnable.class)); } @Test public void testScheduleJobRemoveShouldUseHousekeepingButAlreadyRemoved() { Mockito.when(schedulerDBManager.loadJobWithTasksIfNotRemoved(any(JobId.class))).thenReturn(null); JobId jobId = JobIdImpl.makeJobId("42"); schedulingService.scheduleJobRemove(jobId, 42); Mockito.verify(schedulerDBManager).loadJobWithTasksIfNotRemoved(jobId); } @Test public void testScheduleJobRemoveShouldUseHousekeeping() { JobId jobId = JobIdImpl.makeJobId("42"); InternalJob mockedInternalJob = createMockedInternalJob(jobId); Mockito.when(schedulerDBManager.loadJobWithTasksIfNotRemoved(any(JobId.class))).thenReturn(mockedInternalJob); schedulingService.scheduleJobRemove(jobId, 42); // second case: the job is not null Mockito.verify(schedulerDBManager).loadJobWithTasksIfNotRemoved(jobId); Mockito.verify(schedulerDBManager).scheduleJobForRemoval(eq(jobId), eq(42L), anyBoolean()); } @Test public void testRemoveJobShouldUseClientOperationsThreadPool() { ExecutorService threadPool = Executors.newFixedThreadPool(1); Mockito.when(infrastructure.getClientOperationsThreadPool()).thenReturn(threadPool); Mockito.when(infrastructure.getDBManager()).thenReturn(Mockito.mock(SchedulerDBManager.class)); schedulingService.removeJob(JobIdImpl.makeJobId("43")); Mockito.verify(infrastructure).getClientOperationsThreadPool(); } private InternalJob createMockedInternalJob(JobId jobId) { JobInfo jobInfo = Mockito.mock(JobInfoImpl.class); InternalJob internalJob = Mockito.mock(InternalJob.class); Mockito.when(jobInfo.getJobId()).thenReturn(jobId); Mockito.when(internalJob.getJobInfo()).thenReturn(jobInfo); Mockito.when(internalJob.getOwner()).thenReturn("MOCKED OWNER"); return internalJob; } }