/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
*
* This program 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, either version 3 of the License, or
* (at your option) any later version.
*
* 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/>.
*/
package org.libreplan.business.test.planner.entities;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import org.joda.time.LocalDate;
import org.junit.Test;
import org.libreplan.business.planner.entities.ResourceAllocation;
import org.libreplan.business.planner.entities.Stretch;
import org.libreplan.business.planner.entities.StretchesFunction;
import org.libreplan.business.planner.entities.StretchesFunction.Interval;
import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workingday.IntraDayDate;
/**
* Tests for {@link StretchesFunction} entity.
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
*/
public class StretchesFunctionTest {
private static final LocalDate START_DATE = new LocalDate();
private static final LocalDate END_DATE = START_DATE.plusDays(10);
private StretchesFunction stretchesFunction;
private ResourceAllocation<?> resourceAllocation;
private ResourceAllocation<?> givenResourceAllocation() {
resourceAllocation = createNiceMock(ResourceAllocation.class);
expect(resourceAllocation.getStartDate()).andReturn(START_DATE).anyTimes();
expect(resourceAllocation.getEndDate()).andReturn(END_DATE).anyTimes();
expect(resourceAllocation.getIntraDayStartDate())
.andReturn(IntraDayDate.create(START_DATE, EffortDuration.zero()))
.anyTimes();
expect(resourceAllocation.getIntraDayEndDate())
.andReturn(IntraDayDate.create(END_DATE, EffortDuration.zero()))
.anyTimes();
replay(resourceAllocation);
return resourceAllocation;
}
private StretchesFunction givenStretchesFunction() {
stretchesFunction = StretchesFunction.create();
stretchesFunction.setResourceAllocation(givenResourceAllocation());
return stretchesFunction;
}
private Stretch givenStretchAsChild() {
Stretch result = new Stretch();
stretchesFunction.addStretch(result);
return result;
}
private Stretch givenStretchAsChild(BigDecimal lengthPercentage, BigDecimal amountWorkPercentage) {
Stretch stretch = givenStretchAsChild();
stretch.setLengthPercentage(lengthPercentage);
stretch.setAmountWorkPercentage(amountWorkPercentage);
return stretch;
}
private Stretch givenStretchAsChild(LocalDate date, BigDecimal amountWorkPercentage) {
return givenStretchAsChild(Stretch.getLengthProportionByDate(resourceAllocation, date), amountWorkPercentage);
}
@Test
public void stretchesFunctionCheckNoEmpty1() {
givenStretchesFunction();
assertFalse(stretchesFunction.isNoEmptyConstraint());
}
@Test
public void stretchesFunctionCheckNoEmpty2() {
givenStretchesFunction();
givenStretchAsChild();
assertTrue(stretchesFunction.isNoEmptyConstraint());
}
@Test
public void stretchesFunctionCheckOneHundredPercent1() {
givenStretchesFunction();
assertTrue(stretchesFunction.isOneHundredPercentConstraint());
}
@Test
public void stretchesFunctionCheckOneHundredPercent2() {
givenStretchesFunction();
givenStretchAsChild();
assertTrue(stretchesFunction.isOneHundredPercentConstraint());
}
@Test
public void stretchesFunctionCheckStretchesOrder1() {
givenStretchesFunction();
assertTrue(stretchesFunction.isStretchesOrderConstraint());
}
@Test
public void stretchesFunctionCheckStretchesOrder2() {
givenStretchesFunction();
givenStretchAsChild();
assertFalse(stretchesFunction.isStretchesOrderConstraint());
}
@Test
public void stretchesFunctionCheckStretchesOrder3() {
givenStretchesFunction();
givenStretchAsChild();
givenStretchAsChild();
assertFalse(stretchesFunction.isStretchesOrderConstraint());
}
@Test
public void stretchesFunctionCheckStretchesOrder4() {
givenStretchesFunction();
givenStretchAsChild();
givenStretchAsChild(BigDecimal.ONE, BigDecimal.ONE);
assertFalse(stretchesFunction.isStretchesOrderConstraint());
}
@Test
public void stretchesFunctionCheckStretchesOrder5() {
givenStretchesFunction();
givenStretchAsChild();
givenStretchAsChild(BigDecimal.ZERO, BigDecimal.ZERO);
assertFalse(stretchesFunction.isStretchesOrderConstraint());
}
@Test
public void stretchesFunctionCheckStretchesOrder7() {
givenStretchesFunction();
givenStretchAsChild();
givenStretchAsChild(BigDecimal.ONE, BigDecimal.ONE);
assertFalse(stretchesFunction.isStretchesOrderConstraint());
}
@Test
public void stretchesFunctionCheckStretchesOrder6() {
givenStretchesFunction();
givenStretchAsChild();
givenStretchAsChild(BigDecimal.ONE, BigDecimal.ONE);
assertFalse(stretchesFunction.isStretchesOrderConstraint());
}
@Test
public void stretchesFunctionCheckStretchesOrder8() {
givenStretchesFunction();
givenStretchAsChild(BigDecimal.ONE, BigDecimal.ONE);
assertFalse(stretchesFunction.isStretchesOrderConstraint());
}
@Test
public void stretchesFunctionCheckStretchesOrder9() {
givenStretchesFunction();
givenStretchAsChild(BigDecimal.ZERO, BigDecimal.ZERO);
assertFalse(stretchesFunction.isStretchesOrderConstraint());
}
@Test
public void ifNoStretchesNoIntervalDefinedByStretches() {
givenStretchesFunction();
assertThat(stretchesFunction.getIntervalsDefinedByStretches().size(), equalTo(2));
}
@Test
public void theLastStretchMustHaveAllTheLoad() {
givenStretchesFunction();
givenStretchAsChild(new LocalDate().plusDays(1), BigDecimal.valueOf(0.6));
List<Interval> intervals = stretchesFunction.getIntervalsDefinedByStretches();
assertThat(intervals.size(), equalTo(3));
assertThat(intervals.get(intervals.size() - 1).getLoadProportion(), equalTo(BigDecimal.valueOf(0.4).setScale(2)));
}
@Test
public void oneStretchImpliesThreeInterval() {
givenStretchesFunction();
givenStretchAsChild(new LocalDate().plusDays(1), new BigDecimal(1));
assertThat(stretchesFunction.getIntervalsDefinedByStretches().size(), equalTo(3));
}
@Test
public void oneStretchImpliesOneIntervalUntilDateWithLoadSpecifiedByStretch() {
givenStretchesFunction();
LocalDate stretchDate = new LocalDate().plusDays(1);
BigDecimal amountOfWorkProportion = BigDecimal.valueOf(0.5).setScale(2);
givenStretchAsChild(stretchDate, amountOfWorkProportion);
givenStretchAsChild(new LocalDate().plusDays(2), BigDecimal.valueOf(1.0));
Interval firstInterval = stretchesFunction.getIntervalsDefinedByStretches().get(1);
assertThat(firstInterval.getEnd(), equalTo(stretchDate));
assertFalse(firstInterval.hasNoStart());
assertThat(firstInterval.getLoadProportion(), equalTo(amountOfWorkProportion));
}
@Test
public void theLastIntervalHasStart() {
givenStretchesFunction();
LocalDate stretchDate = new LocalDate().plusDays(1);
givenStretchAsChild(stretchDate, new BigDecimal(0.5));
givenStretchAsChild(stretchDate.plusDays(2), new BigDecimal(1));
Interval lastInterval = stretchesFunction.getIntervalsDefinedByStretches().get(2);
assertThat(lastInterval.getStart(), equalTo(stretchDate));
}
@Test
public void aIntervalInTheMiddleHasStart() {
givenStretchesFunction();
LocalDate start = new LocalDate().plusDays(1);
givenStretchAsChild(start, new BigDecimal(0.5));
LocalDate middleEnd = start.plusDays(2);
givenStretchAsChild(middleEnd, new BigDecimal(0.6));
givenStretchAsChild(middleEnd.plusDays(3), new BigDecimal(1));
Interval middle = stretchesFunction.getIntervalsDefinedByStretches().get(2);
assertFalse(middle.hasNoStart());
assertThat(middle.getStart(), equalTo(start));
assertThat(middle.getEnd(), equalTo(middleEnd));
}
@Test
public void eachIntervalHasTheCorrespondingLoadForThatInterval() {
givenStretchesFunction();
LocalDate start = new LocalDate().plusDays(1);
givenStretchAsChild(start, new BigDecimal(0.5));
LocalDate middleEnd = start.plusDays(2);
givenStretchAsChild(middleEnd, new BigDecimal(0.8));
givenStretchAsChild(middleEnd.plusDays(3), new BigDecimal(1));
Interval first = stretchesFunction.getIntervalsDefinedByStretches().get(1);
Interval middle = stretchesFunction.getIntervalsDefinedByStretches().get(2);
Interval last = stretchesFunction.getIntervalsDefinedByStretches().get(3);
assertThat(first.getLoadProportion(), equalTo(new BigDecimal(0.5).setScale(2)));
assertThat(middle.getLoadProportion(), equalTo(new BigDecimal(0.3).setScale(2, RoundingMode.HALF_EVEN)));
assertThat(last.getLoadProportion(), equalTo(new BigDecimal(0.2).setScale(2, RoundingMode.HALF_EVEN)));
}
@Test
public void ifTheIntervalStartIsNullReturnsThePassedStartDate() {
LocalDate end = new LocalDate().plusMonths(1);
Interval interval = new Interval(new BigDecimal(0.3), null, end);
LocalDate now = new LocalDate();
assertThat(interval.getStartFor(now), equalTo(now));
}
@Test(expected = NullPointerException.class)
public void endDateCannotBeNull() {
LocalDate start = new LocalDate().plusMonths(1);
new Interval(new BigDecimal(0.3), start, null);
}
@Test
public void ifTheIntervalStartIsNotNullReturnsItsStartDate() {
LocalDate start = new LocalDate().plusMonths(1);
Interval interval = new Interval(new BigDecimal(0.3), start, start.plusDays(20));
assertThat(interval.getStartFor(new LocalDate()), equalTo(start));
}
@Test
public void ifTheIntervalEndIsNotNullReturnsItsEndDate() {
LocalDate start = new LocalDate().plusMonths(1);
LocalDate end = new LocalDate().plusMonths(2);
Interval interval = new Interval(new BigDecimal(0.3), start, end);
assertThat(interval.getEnd(), equalTo(end));
}
@Test
public void checkCalculatedDateForStretches() {
givenStretchesFunction();
givenStretchAsChild(BigDecimal.valueOf(0.2), BigDecimal.valueOf(0.5));
givenStretchAsChild(BigDecimal.valueOf(0.5), BigDecimal.valueOf(0.8));
List<Interval> intervals = stretchesFunction.getIntervalsDefinedByStretches();
assertNull(intervals.get(0).getStart());
assertThat(intervals.get(0).getEnd(), equalTo(START_DATE));
assertThat(intervals.get(1).getStart(), equalTo(START_DATE));
assertThat(intervals.get(1).getEnd(), equalTo(START_DATE.plusDays(2)));
assertThat(intervals.get(2).getStart(), equalTo(START_DATE.plusDays(2)));
assertThat(intervals.get(2).getEnd(), equalTo(START_DATE.plusDays(5)));
assertThat(intervals.get(3).getStart(), equalTo(START_DATE.plusDays(5)));
assertThat(intervals.get(3).getEnd(), equalTo(END_DATE));
}
}