/* * Copyright 2017 ThoughtWorks, Inc. * * 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.thoughtworks.go.domain; import com.thoughtworks.go.helper.StageMother; import com.thoughtworks.go.util.TimeProvider; import com.thoughtworks.go.utils.Timeout; import org.joda.time.DateTime; import org.joda.time.DateTimeUtils; import org.joda.time.Duration; import org.junit.Before; import org.junit.Test; import java.sql.Timestamp; import java.util.Date; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.*; public class StageTest { DateTime time1 = new DateTime(2008, 2, 22, 12, 22, 23, 0); DateTime time2 = new DateTime(2008, 2, 22, 12, 22, 24, 0); DateTime time3 = new DateTime(2008, 2, 22, 12, 22, 25, 0); DateTime time4 = new DateTime(2008, 2, 22, 12, 22, 26, 0); private JobInstances jobInstances; private Stage stage; private JobInstance firstJob; private JobInstance secondJob; private static final Date JOB_SCHEDULE_DATE = new Date(); private TimeProvider timeProvider; private long nextId = 0; @Before public void setUp() { timeProvider = new TimeProvider() { @Override public Date currentTime() { return JOB_SCHEDULE_DATE; } public DateTime currentDateTime() { throw new UnsupportedOperationException("Not implemented"); } public DateTime timeoutTime(Timeout timeout) { throw new UnsupportedOperationException("Not implemented"); } }; firstJob = new JobInstance("first-job", timeProvider); secondJob = new JobInstance("second-job", timeProvider); jobInstances = new JobInstances(firstJob, secondJob); stage = StageMother.custom("test", jobInstances); } @Test public void shouldUpdateCompletedByTransitionIdAndStageState() throws Exception { assertThat(stage.getCompletedByTransitionId(), is(nullValue())); DateTime fiveMinsForNow = new DateTime().plusMinutes(5); complete(firstJob, fiveMinsForNow); complete(secondJob, fiveMinsForNow); JobStateTransition lastTransition = secondJob.getTransition(JobState.Completed); stage.calculateResult(); assertThat(stage.getCompletedByTransitionId(), is(nextId)); assertThat(stage.getState(), is(StageState.Passed)); } @Test public void shouldAnswerIsScheduledTrueWhenAllJobsAreInScheduleState() throws Exception { stage.setCounter(1); firstJob.setState(JobState.Scheduled); secondJob.setState(JobState.Scheduled); assertThat(stage.isScheduled(), is(true)); } @Test public void shouldAnswerIsScheduledFalseWhenAJobIsNotInScheduledState() { stage.setCounter(1); firstJob.setState(JobState.Scheduled); secondJob.setState(JobState.Completed); assertThat(stage.isScheduled(), is(false)); } @Test public void shouldAnswerIsScheduledFalseWhenAStageIsAReRun() { stage.setCounter(2); firstJob.setState(JobState.Scheduled); secondJob.setState(JobState.Scheduled); assertThat(stage.isScheduled(), is(false)); } @Test public void shouldAnswerIsReRunTrueWhenAllJobsAreInScheduleState() throws Exception { stage.setCounter(2); stage.setRerunOfCounter(null); firstJob.setState(JobState.Scheduled); secondJob.setState(JobState.Scheduled); assertThat(stage.isReRun(), is(true)); } @Test public void shouldAnswerIsReRunFalseWhenAJobIsNotInScheduledState() { stage.setCounter(2); stage.setRerunOfCounter(null); firstJob.setState(JobState.Scheduled); secondJob.setState(JobState.Completed); assertThat(stage.isReRun(), is(false)); } @Test public void shouldAnswerIsReRunFalseWhenStageIsScheduledFirstTime() { stage.setCounter(1); stage.setRerunOfCounter(null); firstJob.setState(JobState.Scheduled); secondJob.setState(JobState.Scheduled); assertThat(stage.isReRun(), is(false)); } @Test public void shouldAnswerIsReRunTrueWhenAllReRunJobsAreInScheduleState() { stage.setCounter(2); stage.setRerunOfCounter(1); firstJob.setRerun(true); firstJob.setState(JobState.Scheduled); secondJob.setRerun(false); secondJob.setState(JobState.Completed); assertThat(stage.isReRun(), is(true)); } @Test public void shouldAnswerIsReRunFalseWhenAReRunJobIsNotInScheduleState() { stage.setCounter(2); stage.setRerunOfCounter(1); firstJob.setRerun(true); firstJob.setState(JobState.Building); secondJob.setRerun(false); secondJob.setState(JobState.Completed); assertThat(stage.isReRun(), is(false)); } private void complete(JobInstance job, DateTime fiveMinsForNow) { job.completing(JobResult.Passed, fiveMinsForNow.toDate()); job.completed(fiveMinsForNow.plusSeconds(10).toDate()); assignIdsToAllTransitions(job); } private void assignIdsToAllTransitions(JobInstance job) { for (JobStateTransition jobStateTransition : job.getTransitions()) { jobStateTransition.setId(++nextId); } } @Test public void shouldReturnMostRecentCompletedTransitionAsCompletedDateIfLatestTransitionIdIsNot() { firstJob.assign("AGENT-1", time1.toDate()); firstJob.completing(JobResult.Passed, time2.toDate()); firstJob.completed(time2.toDate()); secondJob.assign("AGENT-2", time3.toDate()); secondJob.completing(JobResult.Passed, time4.toDate()); secondJob.completed(time4.toDate()); secondJob.getTransitions().byState(JobState.Completed).setId(1); stage.calculateResult(); assertThat(stage.completedDate(), is(time4.toDate())); } @Test public void shouldReturnNullAsCompletedDateIfNeverCompleted() { firstJob.assign("AGENT-1", time1.toDate()); secondJob.assign("AGENT-2", time3.toDate()); assertNull("Completed date should be null", stage.completedDate()); } @Test public void stageStateShouldBeUnkownIfNoJobs() { Stage newStage = new Stage(); assertThat(newStage.stageState(), is(StageState.Unknown)); } @Test public void shouldCalculateTotalTimeFromFirstScheduledJobToLastCompletedJob() { final DateTime time0 = new DateTime(2008, 2, 22, 10, 21, 23, 0); timeProvider = new TimeProvider() { @Override public Date currentTime() { return time0.toDate(); } public DateTime currentDateTime() { throw new UnsupportedOperationException("Not implemented"); } public DateTime timeoutTime(Timeout timeout) { throw new UnsupportedOperationException("Not implemented"); } }; firstJob = new JobInstance("first-job", timeProvider); secondJob = new JobInstance("second-job", timeProvider); jobInstances = new JobInstances(firstJob, secondJob); stage = StageMother.custom("test", jobInstances); firstJob.assign("AGENT-1", time1.toDate()); firstJob.completing(JobResult.Passed, time2.toDate()); firstJob.completed(time2.toDate()); secondJob.assign("AGENT-2", time3.toDate()); secondJob.completing(JobResult.Passed, time4.toDate()); secondJob.completed(time4.toDate()); stage.calculateResult(); stage.setCreatedTime(new Timestamp(time0.toDate().getTime())); stage.setLastTransitionedTime(new Timestamp(time4.toDate().getTime())); RunDuration.ActualDuration expectedDuration = new RunDuration.ActualDuration(new Duration(time0, time4)); RunDuration.ActualDuration duration = (RunDuration.ActualDuration) stage.getDuration(); assertThat(duration, is(expectedDuration)); assertThat(duration.getTotalSeconds(), is(7263L)); } @Test public void shouldReturnZeroDurationForIncompleteStage() { firstJob.assign("AGENT-1", time1.toDate()); firstJob.changeState(JobState.Building, time2.toDate()); assertThat(stage.getDuration(), is(RunDuration.IN_PROGRESS_DURATION)); } @Test public void shouldReturnLatestTransitionDate() { Date date = JOB_SCHEDULE_DATE; firstJob.completing(JobResult.Failed, date); assertThat(stage.latestTransitionDate(), is(date)); } @Test public void shouldReturnCreatedDateWhenNoTranstions() throws Exception { stage = new Stage("dev", new JobInstances(), "anonymous", "manual", new TimeProvider()); assertEquals(new Date(stage.getCreatedTime().getTime()), stage.latestTransitionDate()); } @Test public void shouldCreateAStageWithAGivenConfigVersion() { Stage stage = new Stage("foo-stage", new JobInstances(), "admin", "manual", false, false, "git-sha", new TimeProvider()); assertThat(stage.getConfigVersion(), is("git-sha")); stage = new Stage("foo-stage", new JobInstances(), "admin", "manual", new TimeProvider()); assertThat(stage.getConfigVersion(), is(nullValue())); } @Test public void shouldSetTheCurrentTimeAsCreationTimeForRerunOfJobs() { Stage stage = new Stage("foo-stage", new JobInstances(), "admin", "manual", false, false, "git-sha", new TimeProvider()); Timestamp createdTimeOfRun1 = stage.getCreatedTime(); long minuteAfter = DateTimeUtils.currentTimeMillis() + 60000; freezeTime(minuteAfter); stage.prepareForRerunOf(new DefaultSchedulingContext("admin"), "git-sha"); resetTime(); Timestamp createdTimeOfRun2 = stage.getCreatedTime(); assertNotEquals(createdTimeOfRun1, createdTimeOfRun2); assertEquals(createdTimeOfRun2, new Timestamp(minuteAfter)); } private void freezeTime(Long millis) { DateTimeUtils.setCurrentMillisFixed(millis); } private void resetTime() { DateTimeUtils.setCurrentMillisSystem(); } }