/* * 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.resources.daos; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.libreplan.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE; import static org.libreplan.business.test.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_TEST_FILE; import java.util.Collection; import java.util.List; import java.util.UUID; import org.junit.Test; import org.junit.runner.RunWith; import org.libreplan.business.common.IAdHocTransactionService; import org.libreplan.business.common.IOnTransaction; import org.libreplan.business.common.exceptions.InstanceNotFoundException; import org.libreplan.business.common.exceptions.ValidationException; import org.libreplan.business.resources.daos.ICriterionDAO; import org.libreplan.business.resources.daos.ICriterionTypeDAO; import org.libreplan.business.resources.entities.Criterion; import org.libreplan.business.resources.entities.CriterionType; import org.libreplan.business.resources.entities.ICriterion; import org.libreplan.business.resources.entities.ICriterionType; import org.libreplan.business.resources.entities.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; /** * Test cases for CriterionDAO. * <br /> * @author Óscar González Fernández <ogonzalez@igalia.com> */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE, BUSINESS_SPRING_CONFIG_TEST_FILE }) public class CriterionDAOTest { @Autowired private ICriterionDAO criterionDAO; @Autowired private ICriterionTypeDAO criterionTypeDAO; @Autowired private IAdHocTransactionService transactionService; private Criterion criterion; @Test @Transactional public void testInSpringContainer() { assertNotNull(criterionDAO); } public static Criterion createValidCriterion() { return createValidCriterion(UUID.randomUUID().toString()); } public static Criterion createValidCriterion(String name) { CriterionType criterionType = CriterionTypeDAOTest.createValidCriterionType(); return Criterion.withNameAndType(name, criterionType); } private CriterionType ensureTypeExists(CriterionType criterionType) { if (criterionTypeDAO.existsOtherCriterionTypeByName(criterionType)) { try { /* Do not remove it */ return criterionType = criterionTypeDAO.findUniqueByName(criterionType); } catch (InstanceNotFoundException e) { throw new RuntimeException(e); } } else { criterionTypeDAO.save(criterionType); return criterionType; } } @Test(expected = InvalidDataAccessApiUsageException.class) @Transactional public void aCriterionRelatedToATransientTypeCannotBeSaved() { givenACriterionWithATransientCriterionType(); criterionDAO.save(criterion); } private void givenACriterionWithATransientCriterionType() { this.criterion = createValidCriterion(); } @Test @Transactional public void afterSavingACriterionItExists() { givenACriterionWithAnExistentType(); criterionDAO.save(criterion); assertTrue(criterionDAO.exists(criterion.getId())); } @Test @Transactional public void afterRemovingTheCriterionNoLongerExists() throws InstanceNotFoundException { givenACriterionWithAnExistentType(); criterionDAO.save(criterion); criterionDAO.remove(criterion.getId()); assertFalse(criterionDAO.exists(criterion.getId())); } private Criterion givenACriterionWithAnExistentType() { this.criterion = createValidCriterion(); CriterionType type = ensureTypeExists(CriterionTypeDAOTest.createValidCriterionType()); this.criterion.setType(type); return this.criterion; } private Criterion givenUniquelyNamedCriterion() { return givenACriterionWithAnExistentType(); } @Test @Transactional public void listReturnsTheNewlyCreatedCriterions() { int previous = criterionDAO.list(Criterion.class).size(); givenASavedCriterionWithAnExistentType(); givenASavedCriterionWithAnExistentType(); List<Criterion> list = criterionDAO.list(Criterion.class); assertEquals(previous + 2, list.size()); } private Criterion givenASavedCriterionWithAnExistentType() { Criterion c = givenACriterionWithAnExistentType(); criterionDAO.save(c); return c; } @Test(expected = DataIntegrityViolationException.class) @Transactional public void schemaEnsuresCannotExistTwoDifferentCriterionsWithSameNameAndType() throws ValidationException { Criterion c = givenASavedCriterionWithAnExistentType(); Criterion repeated = anotherCriterionWithSameNameAndType(c); criterionDAO.save(repeated); criterionDAO.flush(); } private Criterion anotherCriterionWithSameNameAndType(Criterion c) { return Criterion.create(c.getName(), c.getType()); } @Test @Transactional public void findByTypeOnlyReturnsTheCriterionsMatchedByType() { givenASavedCriterionWithAnExistentType(); // saving another givenASavedCriterionWithAnExistentType(); ICriterionType<Criterion> type = createTypeThatMatches(criterion); Collection<Criterion> criterions = criterionDAO.findByType(type); assertEquals(1, criterions.size()); assertTrue(criterions.contains(criterion)); } @Test public void thereIsOtherWithSameNameAndTypeWorksIsolatedFromCurrentTransaction() { transactionService.runOnTransaction(new IOnTransaction<Void>() { @Override public Void execute() { Criterion saved = givenASavedCriterionWithAnExistentType(); assertFalse(criterionDAO.thereIsOtherWithSameNameAndType(saved)); return null; } }); } @Test public void thereIsNoOtherIfItsTheSame() { Criterion c = transactionService.runOnTransaction(new IOnTransaction<Criterion>() { @Override public Criterion execute() { return givenASavedCriterionWithAnExistentType(); } }); assertFalse(criterionDAO.thereIsOtherWithSameNameAndType(c)); } @Test public void ifItsDifferentThereIsOther() { Criterion c = transactionService.runOnTransaction(new IOnTransaction<Criterion>() { @Override public Criterion execute() { return givenASavedCriterionWithAnExistentType(); } }); Criterion copy = Criterion.create(c.getName(), c.getType()); assertTrue(criterionDAO.thereIsOtherWithSameNameAndType(copy)); } @Test @Transactional public void noOtherIfTheCriterionDoesNotExist() { Criterion criterion = givenUniquelyNamedCriterion(); assertFalse(criterionDAO.thereIsOtherWithSameNameAndType(criterion)); } private static ICriterionType<Criterion> createTypeThatMatches(final Criterion criterion) { return createTypeThatMatches(false, criterion); } private static ICriterionType<Criterion> createTypeThatMatches( final boolean allowSimultaneousCriterionsPerResource, final Criterion criterion) { return new ICriterionType<Criterion>() { @Override public boolean isAllowSimultaneousCriterionsPerResource() { return allowSimultaneousCriterionsPerResource; } @Override public boolean allowHierarchy() { return false; } @Override public boolean contains(ICriterion c) { return c instanceof Criterion && criterion.isEquivalent((Criterion) c); } @Override public Criterion createCriterion(String name) { return null; } @Override public String getName() { return null; } @Override public boolean criterionCanBeRelatedTo( Class<? extends Resource> klass) { return true; } @Override public Criterion createCriterionWithoutNameYet() { return null; } @Override public String getDescription() { return null; } @Override public boolean isEnabled() { return true; } @Override public boolean isImmutable() { return false; } }; } }