@Test public void shouldCancelBuildsForDeletedJobsWhenPipelineConfigChanges() throws Exception { fixture = new PipelineWithTwoStages(materialRepository, transactionTemplate).usingTwoJobs(); fixture.usingConfigHelper(configHelper).usingDbHelper(dbHelper).onSetUp(); fixture.createPipelineWithFirstStageScheduled(); buildAssignmentService.onTimer(); configHelper.removeJob(fixture.pipelineName, fixture.devStage, fixture.JOB_FOR_DEV_STAGE); buildAssignmentService.onPipelineConfigChange( goConfigService .getCurrentConfig() .getPipelineConfigByName(new CaseInsensitiveString(fixture.pipelineName)), "g1"); Pipeline pipeline = pipelineDao.mostRecentPipeline(fixture.pipelineName); JobInstance deletedJob = pipeline.getFirstStage().getJobInstances().getByName(fixture.JOB_FOR_DEV_STAGE); assertThat(deletedJob.getState(), is(JobState.Completed)); assertThat(deletedJob.getResult(), is(JobResult.Cancelled)); JobInstance retainedJob = pipeline.getFirstStage().getJobInstances().getByName(fixture.DEV_STAGE_SECOND_JOB); assertThat(retainedJob.getState(), is(JobState.Scheduled)); assertThat(retainedJob.getResult(), is(JobResult.Unknown)); }
@Test public void shouldForceFirstStagePlanWhenOtherStageIsRunning() throws Exception { pipelineWithTwoStages = new PipelineWithTwoStages(materialRepository, transactionTemplate); pipelineWithTwoStages.usingDbHelper(dbHelper).usingConfigHelper(configHelper).onSetUp(); pipelineWithTwoStages.createPipelineWithFirstStagePassedAndSecondStageRunning(); Pipeline pipeline = manualSchedule(pipelineWithTwoStages.pipelineName); assertThat(pipeline.getFirstStage().isActive(), is(true)); }
@Test public void shouldOnlyAssignWorkToIdleAgentsRegisteredInAgentRemoteHandler() { AgentConfig agentConfig = AgentMother.remoteAgent(); configHelper.addAgent(agentConfig); fixture.createPipelineWithFirstStageScheduled(); AgentRuntimeInfo info = AgentRuntimeInfo.fromServer(agentConfig, true, "location", 1000000l, "OS"); info.setCookie("cookie"); AgentStatus[] statuses = new AgentStatus[] { AgentStatus.Building, AgentStatus.Pending, AgentStatus.Disabled, AgentStatus.Disabled, AgentStatus.LostContact, AgentStatus.Missing }; for (AgentStatus status : statuses) { info.setStatus(status); agent = new AgentStub(); agentRemoteHandler.process(agent, new Message(Action.ping, info)); buildAssignmentService.onTimer(); assertThat( "Should not assign work when agent status is " + status, agent.messages.size(), is(0)); } }
@Test public void shouldUpdateResultOfStageWhenJobCompletes() throws Exception { // ScheduleService service = new ScheduleService(goConfigService, pipelineService, // stageService, currentActivityService, schedulingChecker, pipelineScheduledTopic, pipelineDao, // stageDao, stageOrderService, securityService, pipelineScheduleQueue, // jobInstanceService, jobInstanceDao, agentAssignment, environmentConfigService, // pipelineLockService, serverHealthService, transactionTemplate, agentService); Pipeline assigned = preCondition.createPipelineWithFirstStageAssigned(); Stage stage = assigned.findStage(preCondition.devStage); StageSummaryModel model = stageService.findStageSummaryByIdentifier( stage.getIdentifier(), new Username(new CaseInsensitiveString("foo")), new HttpLocalizedOperationResult()); assertThat(model.getStage().getFirstJob().getState(), is(JobState.Assigned)); scheduleService.updateJobStatus(stage.getFirstJob().getIdentifier(), JobState.Building); StageSummaryModel reloadedModel = stageService.findStageSummaryByIdentifier( stage.getIdentifier(), new Username(new CaseInsensitiveString("foo")), new HttpLocalizedOperationResult()); assertThat(reloadedModel.getStage().getFirstJob().getState(), is(JobState.Building)); }
@Test public void shouldUpdateResultOfStageWhenJobCompletes_irrespectiveOfOtherThreadsPrimingStageCache() throws Exception { Pipeline assigned = preCondition.createPipelineWithFirstStageAssigned(); Stage stage = assigned.findStage(preCondition.devStage); StageSummaryModel model = stageService.findStageSummaryByIdentifier( stage.getIdentifier(), new Username(new CaseInsensitiveString("foo")), new HttpLocalizedOperationResult()); JobIdentifier identifier = stage.getFirstJob().getIdentifier(); scheduleService.updateJobStatus(identifier, JobState.Building); scheduleService.jobCompleting(identifier, JobResult.Passed, "uuid"); Stage stageLoadedByOtherFlows = stageDao.stageById(stage.getId()); // priming the cache scheduleService.updateJobStatus(stage.getFirstJob().getIdentifier(), JobState.Completed); StageSummaryModel reloadedModel = stageService.findStageSummaryByIdentifier( stage.getIdentifier(), new Username(new CaseInsensitiveString("foo")), new HttpLocalizedOperationResult()); Stage reloadedStage = reloadedModel.getStage(); assertThat(reloadedStage.getFirstJob().getState(), is(JobState.Completed)); assertThat( reloadedStage.getCompletedByTransitionId(), is(reloadedStage.getFirstJob().getTransitions().byState(JobState.Completed).getId())); assertThat(reloadedStage.getResult(), is(StageResult.Passed)); assertThat(reloadedStage.getState(), is(StageState.Passed)); }
@After public void teardown() throws Exception { dbHelper.onTearDown(); preCondition.onTearDown(); pipelineScheduleQueue.clear(); configHelper.onTearDown(); }
private Pipeline tryToScheduleAPipeline() { BuildCause buildCause = BuildCause.createWithModifications(modifyOneFile(preCondition.pipelineConfig()), ""); dbHelper.saveMaterials(buildCause.getMaterialRevisions()); pipelineScheduleQueue.schedule(preCondition.pipelineName, buildCause); scheduleService.autoSchedulePipelinesFromRequestBuffer(); return pipelineService.mostRecentFullPipelineByName(preCondition.pipelineName); }
@Before public void setUp() throws Exception { preCondition = new PipelineWithTwoStages(materialRepository, transactionTemplate); configHelper.usingCruiseConfigDao(goConfigFileDao); configHelper.onSetUp(); dbHelper.onSetUp(); preCondition.usingConfigHelper(configHelper).usingDbHelper(dbHelper).onSetUp(); }
@After public void teardown() throws Exception { goCache.clear(); agentService.clearAll(); fixture.onTearDown(); dbHelper.onTearDown(); configHelper.onTearDown(); FileUtil.deleteFolder(goConfigService.artifactsDir()); agentAssignment.clear(); agentRemoteHandler.connectedAgents().clear(); }
@After public void teardown() throws Exception { if (pipelineWithTwoStages != null) { pipelineWithTwoStages.onTearDown(); } dbHelper.onTearDown(); pipelineScheduleQueue.clear(); testRepo.tearDown(); FileUtil.deleteFolder(new File("pipelines")); configHelper.onTearDown(); }
@Test public void shouldUpdateNumberOfActiveRemoteAgentsAfterAssigned() { AgentConfig agentConfig = AgentMother.remoteAgent(); configHelper.addAgent(agentConfig); fixture.createPipelineWithFirstStageScheduled(); buildAssignmentService.onTimer(); int before = agentService.numberOfActiveRemoteAgents(); Work work = buildAssignmentService.assignWorkToAgent(agent(agentConfig)); assertThat(work, instanceOf(BuildWork.class)); assertThat(agentService.numberOfActiveRemoteAgents(), is(before + 1)); }
@Test public void shouldUpdateResultOfStageWhenJobCompletesOnTransactionCommitOnly() throws Exception { StageService stageService = mock(StageService.class); StageDao stageDao = mock(StageDao.class); SchedulingPerformanceLogger schedulingPerformanceLogger = mock(SchedulingPerformanceLogger.class); ScheduleService service = new ScheduleService( goConfigService, pipelineService, stageService, schedulingChecker, pipelineScheduledTopic, pipelineDao, stageDao, stageOrderService, securityService, pipelineScheduleQueue, jobInstanceService, jobInstanceDao, agentAssignment, environmentConfigService, pipelineLockService, serverHealthService, transactionTemplate, agentService, synchronizationManager, null, null, null, null, schedulingPerformanceLogger); Pipeline assigned = preCondition.createPipelineWithFirstStageAssigned(); Stage stage = assigned.findStage(preCondition.devStage); when(stageService.stageById(stage.getId())).thenThrow(new RuntimeException("find fails")); try { service.updateJobStatus(stage.getFirstJob().getIdentifier(), JobState.Completed); fail("should have failed because stage lookup bombed"); } catch (Exception e) { // ignore } verify(stageDao, never()) .clearCachedAllStages( stage.getIdentifier().getPipelineName(), stage.getIdentifier().getPipelineCounter(), stage.getName()); }
@Test public void shouldCancelOutOfDateBuilds() throws Exception { fixture.createPipelineWithFirstStageScheduled(); buildAssignmentService.onTimer(); configHelper.removeStage(fixture.pipelineName, fixture.devStage); buildAssignmentService.onConfigChange(goConfigService.getCurrentConfig()); Pipeline pipeline = pipelineDao.mostRecentPipeline(fixture.pipelineName); JobInstance job = pipeline.getFirstStage().getJobInstances().first(); assertThat(job.getState(), is(JobState.Completed)); assertThat(job.getResult(), is(JobResult.Cancelled)); }
@Test public void shouldCancelBuildBelongingToNonExistentPipelineWhenCreatingWork() throws Exception { fixture.createPipelineWithFirstStageScheduled(); Pipeline pipeline = pipelineDao.mostRecentPipeline(fixture.pipelineName); ScheduledPipelineLoader scheduledPipelineLoader = mock(ScheduledPipelineLoader.class); when(scheduledPipelineLoader.pipelineWithPasswordAwareBuildCauseByBuildId( pipeline.getFirstStage().getJobInstances().first().getId())) .thenThrow(new PipelineNotFoundException("thrown by mockPipelineService")); GoConfigService mockGoConfigService = mock(GoConfigService.class); CruiseConfig config = configHelper.currentConfig(); configHelper.removePipeline(fixture.pipelineName, config); when(mockGoConfigService.getCurrentConfig()).thenReturn(config); buildAssignmentService = new BuildAssignmentService( mockGoConfigService, jobInstanceService, scheduleService, agentService, environmentConfigService, timeProvider, transactionTemplate, scheduledPipelineLoader, pipelineService, builderFactory, agentRemoteHandler); buildAssignmentService.onTimer(); AgentConfig agentConfig = AgentMother.localAgent(); agentConfig.addResource(new Resource("some-other-resource")); try { buildAssignmentService.assignWorkToAgent(agent(agentConfig)); fail("should have thrown PipelineNotFoundException"); } catch (PipelineNotFoundException e) { // ok } pipeline = pipelineDao.mostRecentPipeline(fixture.pipelineName); JobInstance job = pipeline.getFirstStage().getJobInstances().first(); assertThat(job.getState(), is(JobState.Completed)); assertThat(job.getResult(), is(JobResult.Cancelled)); Stage stage = stageDao.findStageWithIdentifier(job.getIdentifier().getStageIdentifier()); assertThat(stage.getState(), is(StageState.Cancelled)); assertThat(stage.getResult(), is(StageResult.Cancelled)); }
@Test public void shouldNotAssignNoWorkToAgentsRegisteredInAgentRemoteHandler() { AgentConfig agentConfig = AgentMother.remoteAgent(); configHelper.addAgent(agentConfig); fixture.createdPipelineWithAllStagesPassed(); AgentRuntimeInfo info = AgentRuntimeInfo.fromServer(agentConfig, true, "location", 1000000l, "OS"); info.setCookie("cookie"); agentRemoteHandler.process(agent, new Message(Action.ping, info)); buildAssignmentService.onTimer(); assertThat(agent.messages.size(), is(0)); }
@Test public void shouldCallForReregisterIfAgentInstanceIsNotRegistered() { AgentConfig agentConfig = AgentMother.remoteAgent(); fixture.createPipelineWithFirstStageScheduled(); AgentRuntimeInfo info = AgentRuntimeInfo.fromServer(agentConfig, true, "location", 1000000l, "OS"); agentService.requestRegistration(info); assertThat(agentService.findAgent(info.getUUId()).isRegistered(), is(false)); info.setCookie("cookie"); agentRemoteHandler.process(agent, new Message(Action.ping, info)); buildAssignmentService.onTimer(); assertThat(agent.messages.size(), is(1)); assertThat(agent.messages.get(0).getAction(), is(Action.reregister)); }
@Before public void setUp() throws Exception { configHelper = new GoConfigFileHelper().usingCruiseConfigDao(goConfigDao); configHelper.onSetUp(); dbHelper.onSetUp(); fixture = new PipelineWithTwoStages(materialRepository, transactionTemplate); fixture.usingConfigHelper(configHelper).usingDbHelper(dbHelper).onSetUp(); repository = new SvnCommand(null, testRepo.projectRepositoryUrl()); evolveConfig = configHelper.addPipeline("evolve", STAGE_NAME, repository, "unit"); configHelper.addPipeline("anotherPipeline", STAGE_NAME, repository, "anotherTest"); configHelper.addPipeline("thirdPipeline", STAGE_NAME, repository, "yetAnotherTest"); goConfigService.forceNotifyListeners(); goCache.clear(); u = new ScheduleTestUtil(transactionTemplate, materialRepository, dbHelper, configHelper); agent = new AgentStub(); }
@Test public void shouldAssignMatchedJobToAgentsRegisteredInAgentRemoteHandler() { AgentConfig agentConfig = AgentMother.remoteAgent(); configHelper.addAgent(agentConfig); fixture.createPipelineWithFirstStageScheduled(); AgentRuntimeInfo info = AgentRuntimeInfo.fromServer(agentConfig, true, "location", 1000000l, "OS"); info.setCookie("cookie"); agentRemoteHandler.process(agent, new Message(Action.ping, info)); int before = agentService.numberOfActiveRemoteAgents(); buildAssignmentService.onTimer(); assertThat(agent.messages.size(), is(1)); assertThat(agent.messages.get(0).getData(), instanceOf(BuildWork.class)); assertThat(agentService.numberOfActiveRemoteAgents(), is(before + 1)); }
@Test public void shouldNotAssignWorkToCanceledAgentsRegisteredInAgentRemoteHandler() { AgentConfig agentConfig = AgentMother.remoteAgent(); configHelper.addAgent(agentConfig); fixture.createPipelineWithFirstStageScheduled(); AgentRuntimeInfo info = AgentRuntimeInfo.fromServer(agentConfig, true, "location", 1000000l, "OS"); info.setCookie("cookie"); agentRemoteHandler.process(agent, new Message(Action.ping, info)); AgentInstance agentInstance = agentService.findAgentAndRefreshStatus(info.getUUId()); agentInstance.cancel(); buildAssignmentService.onTimer(); assertThat( "Should not assign work when agent status is Canceled", agent.messages.size(), is(0)); }
@Test public void shouldCancelBuildBelongingToNonExistentPipeline() throws Exception { fixture.createPipelineWithFirstStageScheduled(); buildAssignmentService.onTimer(); configHelper.removePipeline(fixture.pipelineName); AgentConfig agentConfig = AgentMother.localAgent(); agentConfig.addResource(new Resource("some-other-resource")); assertThat( (NoWork) buildAssignmentService.assignWorkToAgent(agent(agentConfig)), Matchers.is(BuildAssignmentService.NO_WORK)); Pipeline pipeline = pipelineDao.mostRecentPipeline(fixture.pipelineName); JobInstance job = pipeline.getFirstStage().getJobInstances().first(); assertThat(job.getState(), is(JobState.Completed)); assertThat(job.getResult(), is(JobResult.Cancelled)); Stage stage = stageDao.findStageWithIdentifier(job.getIdentifier().getStageIdentifier()); assertThat(stage.getState(), is(StageState.Cancelled)); assertThat(stage.getResult(), is(StageResult.Cancelled)); }
@Test public void shouldNotReloadScheduledJobPlansWhenAgentWorkAssignmentIsInProgress() throws Exception { fixture.createPipelineWithFirstStageScheduled(); Pipeline pipeline = pipelineDao.mostRecentPipeline(fixture.pipelineName); JobInstance job = pipeline.getFirstStage().getJobInstances().first(); final JobInstanceService mockJobInstanceService = mock(JobInstanceService.class); final Pipeline pipeline1 = pipeline; final Semaphore sem = new Semaphore(1); sem.acquire(); when(mockJobInstanceService.orderedScheduledBuilds()) .thenReturn(jobInstanceService.orderedScheduledBuilds()); when(mockJobInstanceService.buildByIdWithTransitions(job.getId())) .thenReturn(jobInstanceService.buildByIdWithTransitions(job.getId())); ScheduledPipelineLoader scheduledPipelineLoader = new ScheduledPipelineLoader(null, null, null, null, null, null, null, null) { @Override public Pipeline pipelineWithPasswordAwareBuildCauseByBuildId(long buildId) { sem.release(); sleepQuietly(1000); verify(mockJobInstanceService, times(1)).orderedScheduledBuilds(); return pipeline1; } }; final BuildAssignmentService buildAssignmentServiceUnderTest = new BuildAssignmentService( goConfigService, mockJobInstanceService, scheduleService, agentService, environmentConfigService, timeProvider, transactionTemplate, scheduledPipelineLoader, pipelineService, builderFactory, agentRemoteHandler); final Throwable[] fromThread = new Throwable[1]; buildAssignmentServiceUnderTest.onTimer(); Thread assigner = new Thread( new Runnable() { public void run() { try { final AgentConfig agentConfig = AgentMother.localAgentWithResources("some-other-resource"); buildAssignmentServiceUnderTest.assignWorkToAgent(agent(agentConfig)); } catch (Throwable e) { e.printStackTrace(); fromThread[0] = e; } finally { } } }, "assignmentThread"); assigner.start(); sem.acquire(); buildAssignmentServiceUnderTest.onTimer(); assigner.join(); assertThat(fromThread[0], is(nullValue())); }