Package org.libreplan.business.test.calendars.entities

Source Code of org.libreplan.business.test.calendars.entities.AvailabilityTimeLineTest

/*
* 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.calendars.entities;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.Validate;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.joda.time.LocalDate;
import org.junit.Test;
import org.libreplan.business.calendars.entities.AvailabilityTimeLine;
import org.libreplan.business.calendars.entities.AvailabilityTimeLine.DatePoint;
import org.libreplan.business.calendars.entities.AvailabilityTimeLine.EndOfTime;
import org.libreplan.business.calendars.entities.AvailabilityTimeLine.FixedPoint;
import org.libreplan.business.calendars.entities.AvailabilityTimeLine.IVetoer;
import org.libreplan.business.calendars.entities.AvailabilityTimeLine.Interval;
import org.libreplan.business.calendars.entities.AvailabilityTimeLine.StartOfTime;

/**
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
public class AvailabilityTimeLineTest {

    private LocalDate earlyExample = new LocalDate(1000, 10, 6);

    private LocalDate contemporaryExample = new LocalDate(2010, 10, 6);

    private LocalDate lateExample = new LocalDate(3000, 10, 6);

    @Test
    public void anAllValidTimeLineIsValidForAllDates() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        assertTrue(timeLine.isValid(earlyExample));
        assertTrue(timeLine.isValid(contemporaryExample));
        assertTrue(timeLine.isValid(lateExample));
    }

    @Test
    public void canBeAddedInvalidDates() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();

        timeLine.invalidAt(earlyExample);

        assertFalse(timeLine.isValid(earlyExample));
        assertTrue(timeLine.isValid(contemporaryExample));
        assertTrue(timeLine.isValid(lateExample));
    }

    @Test
    public void canBeAddedInvalidIntervals() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();

        LocalDate intervalStart = contemporaryExample.minusDays(10);
        LocalDate intervalEnd = contemporaryExample.plusDays(5);
        timeLine.invalidAt(intervalStart, intervalEnd);

        assertFalse("the start is inclusive", timeLine.isValid(intervalStart));
        assertFalse(timeLine.isValid(contemporaryExample.minusDays(1)));
        assertFalse(timeLine.isValid(contemporaryExample));
        assertFalse(timeLine.isValid(contemporaryExample.plusDays(1)));
        assertTrue("the end is exclusive", timeLine.isValid(intervalEnd));
    }

    @Test
    public void addingAnIntervalThatIsCompletelyInvalidIsIgnored() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        LocalDate intervalStart = contemporaryExample.minusDays(10);
        LocalDate intervalEnd = contemporaryExample.plusDays(5);

        timeLine.invalidAt(intervalStart, intervalEnd);
        timeLine.invalidAt(intervalStart.plusDays(2), intervalEnd.minusDays(2));

        assertFalse(timeLine.isValid(intervalEnd.minusDays(1)));
    }

    @Test
    public void addingAnIntervalThatItsNotCompletelyInvalid() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        LocalDate intervalStart = contemporaryExample.minusDays(10);
        LocalDate intervalEnd = contemporaryExample.plusDays(5);

        timeLine.invalidAt(intervalStart, intervalEnd);
        timeLine.invalidAt(intervalStart.minusDays(3), intervalEnd.plusDays(4));

        assertFalse(timeLine.isValid(intervalStart.minusDays(3)));
        assertFalse(timeLine.isValid(intervalEnd));
        assertFalse(timeLine.isValid(intervalEnd.plusDays(3)));
        assertTrue(timeLine.isValid(intervalEnd.plusDays(4)));
    }

    @Test
    public void addingAnIntervalThatJoinsTwoInvalidIntervals() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        LocalDate intervalStart = contemporaryExample.minusDays(10);
        LocalDate intervalEnd = contemporaryExample.plusDays(5);

        timeLine.invalidAt(intervalStart, intervalEnd);
        timeLine.invalidAt(intervalStart.minusDays(20), intervalStart
                .minusDays(10));
        timeLine.invalidAt(intervalStart.minusDays(10), intervalStart);
        LocalDate current = intervalStart.minusDays(20);
        while (current.isBefore(intervalEnd)) {
            assertFalse(timeLine.isValid(current));
            current = current.plusDays(1);
        }
    }

    @Test
    public void pointsAreMergedCorrectly() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();

        timeLine.invalidAt(new LocalDate(2010, 4, 7));
        timeLine.invalidAt(new LocalDate(2010, 4, 11));
        timeLine.invalidAt(new LocalDate(2010, 4, 8));
        timeLine.invalidAt(new LocalDate(2010, 4, 6));

        assertFalse(timeLine.isValid(new LocalDate(2010, 4, 8)));
    }

    @Test(expected = IllegalArgumentException.class)
    public void endMustBeAfterStart() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        LocalDate intervalStart = contemporaryExample.minusDays(10);
        LocalDate intervalEnd = contemporaryExample.plusDays(5);
        timeLine.invalidAt(intervalEnd, intervalStart);
    }

    @Test
    public void addingFromInterval() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.invalidFrom(contemporaryExample);

        assertFalse(timeLine.isValid(contemporaryExample));
        assertFalse(timeLine.isValid(contemporaryExample.plusDays(10)));
        assertFalse(timeLine.isValid(lateExample));
        assertTrue(timeLine.isValid(contemporaryExample.minusDays(1)));
    }

    @Test
    public void addingToInterval() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.invalidUntil(contemporaryExample);

        assertTrue(timeLine.isValid(contemporaryExample));
        assertTrue(timeLine.isValid(contemporaryExample.plusDays(1)));
        assertFalse(timeLine.isValid(contemporaryExample.minusDays(1)));
        assertFalse(timeLine.isValid(earlyExample));
    }

    @Test
    public void addingAndAlreadyIncludedIntervalToAFromIntervalDoesNothing() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.invalidFrom(contemporaryExample);
        timeLine.invalidAt(contemporaryExample.plusDays(30),
                contemporaryExample.plusDays(100));

        assertFalse(timeLine.isValid(contemporaryExample));
        assertFalse(timeLine.isValid(contemporaryExample.plusDays(10)));
        assertFalse(timeLine.isValid(lateExample));
        assertTrue(timeLine.isValid(contemporaryExample.minusDays(1)));
    }

    @Test
    public void addingAllInvalidMakesAllInvalid() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.invalidFrom(contemporaryExample);
        timeLine.invalidUntil(contemporaryExample.minusDays(10));

        assertFalse(timeLine.isValid(earlyExample));
        assertTrue(timeLine.isValid(contemporaryExample.minusDays(10)));

        assertFalse(timeLine.isValid(contemporaryExample));
        assertFalse(timeLine.isValid(lateExample));

        timeLine.allInvalid();
        assertFalse(timeLine.isValid(earlyExample));
        assertFalse(timeLine.isValid(contemporaryExample.minusDays(10)));
        assertFalse(timeLine.isValid(contemporaryExample));
        assertFalse(timeLine.isValid(lateExample));
    }

    @Test
    public void addingSeveralTypesOfIntervals() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.invalidFrom(contemporaryExample);
        timeLine.invalidUntil(contemporaryExample.minusDays(10));

        assertFalse(timeLine.isValid(earlyExample));
        assertTrue(timeLine.isValid(contemporaryExample.minusDays(10)));

        assertFalse(timeLine.isValid(contemporaryExample));
        assertFalse(timeLine.isValid(lateExample));

        timeLine.invalidAt(contemporaryExample.minusDays(10),
                contemporaryExample);

        assertFalse(timeLine.isValid(contemporaryExample));
        assertFalse(timeLine.isValid(contemporaryExample.plusDays(1)));
        assertFalse(timeLine.isValid(contemporaryExample.minusDays(1)));
        assertFalse(timeLine.isValid(earlyExample));
    }

    @Test
    public void addingTwoAvailabilityTimeLines() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.invalidAt(contemporaryExample.minusDays(10),
                contemporaryExample.plusDays(10));

        AvailabilityTimeLine another = AvailabilityTimeLine.allValid();
        another.invalidAt(contemporaryExample.minusDays(40),
                contemporaryExample.minusDays(20));

        AvailabilityTimeLine result = timeLine.and(another);

        LocalDate current = contemporaryExample.minusDays(40);
        LocalDate end = contemporaryExample.plusDays(20);
        while (current.compareTo(end) < 0) {
            assertEquals("must give the same value for: " + current, timeLine
                    .isValid(current)
                    && another.isValid(current), result.isValid(current));
            current = current.plusDays(1);
        }
    }

    @Test
    public void doingOROnTwoTimeLinesResultingOnAnAllValidTimeLine() {
        AvailabilityTimeLine one = AvailabilityTimeLine.allValid();
        one.invalidAt(contemporaryExample.minusDays(40), contemporaryExample
                .minusDays(20));

        AvailabilityTimeLine another = AvailabilityTimeLine.allValid();
        another.invalidAt(contemporaryExample.minusDays(10),
                contemporaryExample.plusDays(10));

        AvailabilityTimeLine result = one.or(another);

        assertThat(result.getValidPeriods(), definedBy(StartOfTime.create(),
                EndOfTime.create()));
    }

    @Test
    public void doingORonTwoTimeLinesWithSeveralIntersectingInvalidPeriods() {
        AvailabilityTimeLine one = AvailabilityTimeLine.allValid();
        one.invalidAt(contemporaryExample.minusDays(40), contemporaryExample
                .minusDays(20));
        one.invalidAt(contemporaryExample.plusDays(35), contemporaryExample
                .plusDays(50));

        AvailabilityTimeLine another = AvailabilityTimeLine.allValid();
        another.invalidAt(contemporaryExample.minusDays(25),
                contemporaryExample.plusDays(10));
        another.invalidAt(contemporaryExample.plusDays(30), contemporaryExample
                .plusDays(40));

        AvailabilityTimeLine result = one.or(another);

        assertThat(result.getValidPeriods(), definedBy(StartOfTime.create(),
                point(contemporaryExample.minusDays(25)),
                point(contemporaryExample.minusDays(20)),
                point(contemporaryExample.plusDays(35)),
                point(contemporaryExample.plusDays(40)), EndOfTime.create()));
    }

    @Test
    public void doingOROnTheSameTimeLineResultsInTheSameTimeLine() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.invalidAt(earlyExample, contemporaryExample);
        timeLine.invalidAt(lateExample, lateExample.plusDays(20));

        AvailabilityTimeLine result = timeLine.or(timeLine);

        assertThat(result.getValidPeriods(), definedBy(StartOfTime.create(),
                point(earlyExample), point(contemporaryExample),
                point(lateExample), point(lateExample
                        .plusDays(20)), EndOfTime.create()));
    }

    @Test
    public void doingAnORDoesAnOrForAdditionalConstraints() {
        boolean[][] validities = { { true, true }, { true, false },
                { false, true }, { false, false } };
        for (final boolean[] pairs : validities) {
            AvailabilityTimeLine a = AvailabilityTimeLine.allValid();
            a.setVetoer(new IVetoer() {

                @Override
                public boolean isValid(LocalDate date) {
                    return pairs[0];
                }
            });
            AvailabilityTimeLine b = AvailabilityTimeLine.allValid();
            b.setVetoer(new IVetoer() {

                @Override
                public boolean isValid(LocalDate date) {
                    return pairs[1];
                }
            });
            AvailabilityTimeLine result = a.or(b);
            boolean expected = pairs[0] || pairs[1];

            assertThat(result.isValid(earlyExample), equalTo(expected));
            assertThat(result.isValid(contemporaryExample), equalTo(expected));
            assertThat(result.isValid(lateExample), equalTo(expected));
        }
    }

    @Test
    public void doingAnAndWithAnAllValidTimeLineProducesTheSameTimeLine() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.invalidAt(earlyExample, contemporaryExample);
        timeLine.invalidAt(lateExample, lateExample.plusDays(20));

        AvailabilityTimeLine result = timeLine.and(AvailabilityTimeLine
                .allValid());

        assertThat(result.getValidPeriods(), definedBy(StartOfTime.create(),
                point(earlyExample), point(contemporaryExample),
                point(lateExample), point(lateExample
                        .plusDays(20)), EndOfTime.create()));
    }

    @Test
    public void doingAnAndIntersectsTheAdditionalConstraints() {
        boolean[][] validities = { { true, true }, { true, false },
                { false, true }, { false, false } };
        for (final boolean[] pairs : validities) {
            AvailabilityTimeLine a = AvailabilityTimeLine.allValid();
            a.setVetoer(new IVetoer() {

                @Override
                public boolean isValid(LocalDate date) {
                    return pairs[0];
                }
            });
            AvailabilityTimeLine b = AvailabilityTimeLine.allValid();
            b.setVetoer(new IVetoer() {

                @Override
                public boolean isValid(LocalDate date) {
                    return pairs[1];
                }
            });
            AvailabilityTimeLine result = a.and(b);
            boolean expected = pairs[0] && pairs[1];

            assertThat(result.isValid(earlyExample), equalTo(expected));
            assertThat(result.isValid(contemporaryExample), equalTo(expected));
            assertThat(result.isValid(lateExample), equalTo(expected));
        }
    }

    @Test
    public void doingAnOrWithANeverValidTimeLineProducesTheSameTimeLine() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.invalidAt(earlyExample, contemporaryExample);
        timeLine.invalidAt(lateExample, lateExample.plusDays(20));
        AvailabilityTimeLine another = AvailabilityTimeLine.allValid();
        another.allInvalid();

        AvailabilityTimeLine result = timeLine.and(another);

        assertThat(result.getValidPeriods(), definedBy(StartOfTime.create(),
                point(earlyExample), point(contemporaryExample),
                point(lateExample), point(lateExample.plusDays(20)), EndOfTime
                        .create()));
    }

    @Test
    public void anAllValidPeriodsGeneratesAnAllEncompassingInterval() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        List<Interval> validPeriods = timeLine.getValidPeriods();

        assertThat(validPeriods, definedBy(StartOfTime.create(), EndOfTime
                .create()));
    }

    @Test
    public void anInvalidPeriodUntilGeneratesAValidIntervalAfterwards() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.invalidUntil(contemporaryExample);
        List<Interval> validPeriods = timeLine.getValidPeriods();

        assertThat(validPeriods, definedBy(point(contemporaryExample),
                EndOfTime.create()));
    }

    @Test
    public void anInvalidFromPeriodGeneratesAValidIntervalBefore() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.invalidFrom(contemporaryExample);
        List<Interval> validPeriods = timeLine.getValidPeriods();

        assertThat(validPeriods, definedBy(StartOfTime.create(),
                new FixedPoint(contemporaryExample)));
    }

    @Test
    public void anInvalidityPeriodGeneratesTwoValidIntervals() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.invalidAt(contemporaryExample, lateExample);
        List<Interval> validPeriods = timeLine.getValidPeriods();

        assertThat(validPeriods, definedBy(StartOfTime.create(),
                point(contemporaryExample), point(lateExample), EndOfTime
                        .create()));
    }

    @Test
    public void anAllInvalidTimelineGeneratesZeroValidIntervals() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.allInvalid();
        assertTrue(timeLine.getValidPeriods().isEmpty());
    }

    @Test
    public void anInvalidPointGeneratesTwoValidPeriods() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.invalidAt(contemporaryExample);
        assertThat(timeLine.getValidPeriods(), definedBy(StartOfTime.create(),
                point(contemporaryExample), point(contemporaryExample
                        .plusDays(1)), EndOfTime.create()));
    }

    private static FixedPoint point(LocalDate param) {
        return new FixedPoint(param);
    }

    @Test
    public void aCombinationOfSeveralInvalidPeriods() {
        AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
        timeLine.invalidUntil(earlyExample);
        timeLine.invalidAt(contemporaryExample, lateExample);
        timeLine.invalidFrom(lateExample.plusDays(10));
        assertThat(timeLine.getValidPeriods(), definedBy(point(earlyExample),
                point(contemporaryExample), point(lateExample),
                point(lateExample.plusDays(10))));
    }

    private static Matcher<List<Interval>> definedBy(final DatePoint... points) {
        Validate.isTrue(points.length % 2 == 0,
                "number of points provided must be even");
        return new BaseMatcher<List<Interval>>() {

            @SuppressWarnings("unchecked")
            @Override
            public boolean matches(Object object) {
                if (object instanceof List) {
                    List<Interval> intervals = (List<Interval>) object;
                    List<DatePoint[]> pairsOfPoints = pointsAsPairs();
                    for (int i = 0; i < intervals.size(); i++) {
                        Interval interval = intervals.get(i);
                        DatePoint[] pair = pairsOfPoints.get(i);
                        if (!(pair[0].equals(interval.getStart()) && pair[1]
                                .equals(interval.getEnd()))) {
                            return false;
                        }
                    }
                    return true;
                }
                return false;
            }

            private List<DatePoint[]> pointsAsPairs() {
                List<DatePoint[]> result = new ArrayList<DatePoint[]>();
                for (int i = 0; i < points.length / 2; i++) {
                    DatePoint[] pair = { points[i * 2], points[i * 2 + 1] };
                    result.add(pair);
                }
                return result;
            }

            @Override
            public void describeTo(Description description) {
                StringBuilder text = new StringBuilder();
                boolean first = true;
                for (DatePoint[] each : pointsAsPairs()) {
                    DatePoint start = each[0];
                    DatePoint end = each[1];
                    if (!first) {
                        text.append(", ");
                    }
                    text.append(String.format("[%s, %s]", start, end));
                    first = false;
                }
                description.appendText(text.toString());
            }
        };
    }

}
TOP

Related Classes of org.libreplan.business.test.calendars.entities.AvailabilityTimeLineTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.