/* * Copyright (C) 2005-2007 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * 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 General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * As a special exception to the terms and conditions of version 2.0 of * the GPL, you may redistribute this Program in connection with Free/Libre * and Open Source Software ("FLOSS") applications as described in Alfresco's * FLOSS exception. You should have recieved a copy of the text describing * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ package org.alfresco.repo.dictionary.constraint; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import junit.framework.TestCase; import org.alfresco.i18n.I18NUtil; import org.alfresco.repo.dictionary.DictionaryDAOTest; import org.alfresco.service.cmr.dictionary.Constraint; import org.alfresco.service.cmr.dictionary.ConstraintException; import org.alfresco.service.cmr.dictionary.DictionaryException; /** * This file must be saved using UTF-8. * * @see org.alfresco.service.cmr.dictionary.Constraint * @see org.alfresco.repo.dictionary.constraint.AbstractConstraint * @see org.alfresco.repo.dictionary.constraint.RegexConstraint * * @author Derek Hulley */ @SuppressWarnings("unused") public class ConstraintsTest extends TestCase { @Override protected void setUp() throws Exception { // register resource bundles for messages I18NUtil.registerResourceBundle(DictionaryDAOTest.TEST_RESOURCE_MESSAGES); } /** * ensure that the default handling of checks on collections will work */ public void testCollections() throws Exception { DummyConstraint constraint = new DummyConstraint(); constraint.initialize(); assertEquals("DummyConstraint type should be 'org.alfresco.repo.dictionary.constraint.ConstraintsTest$DummyConstraint'", "org.alfresco.repo.dictionary.constraint.ConstraintsTest$DummyConstraint", constraint.getType()); assertNull("DummyConstraint should not have parameters", constraint.getParameters()); List dummyObjects = new ArrayList(3); dummyObjects.add("ABC"); // correct dummyObjects.add("DEF"); // correct dummyObjects.add(this); // NO try { constraint.evaluate(dummyObjects); fail("Failed to detected constraint violation in collection"); } catch (ConstraintException e) { // expected checkI18NofExceptionMessage(e); } // check that the two strings were properly dealt with assertEquals("String values not checked", 2, constraint.tested.size()); } public void testNull() throws Exception { DummyConstraint constraint = new DummyConstraint(); constraint.initialize(); // a null always passes constraint.evaluate(null); } private void checkI18NofExceptionMessage(Throwable e) { String msg = e.getMessage(); assertFalse("I18N of constraint message failed", msg.startsWith("d_dictionary.constraint")); } private void evaluate(Constraint constraint, Object value, boolean expectFailure) throws Exception { try { constraint.evaluate(value); if (expectFailure) { // it should have failed fail("Failure did not occur: \n" + " constraint: " + constraint + "\n" + " value: " + value); } } catch (ConstraintException e) { // check if we expect an error if (expectFailure) { // expected - check message I18N checkI18NofExceptionMessage(e); } else { // didn't expect it throw e; } } } public void testStringLengthConstraint() throws Exception { StringLengthConstraint constraint = new StringLengthConstraint(); try { constraint.setMinLength(-1); } catch (DictionaryException e) { // expected checkI18NofExceptionMessage(e); } try { constraint.setMaxLength(-1); } catch (DictionaryException e) { // expected checkI18NofExceptionMessage(e); } constraint.setMinLength(3); constraint.setMaxLength(6); assertEquals("StringLengthConstraint type should be 'LENGTH'", "LENGTH", constraint.getType()); assertNotNull("StringLengthConstraint should have parameters", constraint.getParameters()); assertEquals("StringLengthConstraint should have 2 parameters", 2, constraint.getParameters().size()); assertEquals("minLength should be 3", 3, constraint.getParameters().get("minLength")); assertEquals("maxLength should be 6", 6, constraint.getParameters().get("maxLength")); evaluate(constraint, "abc", false); evaluate(constraint, "abcdef", false); evaluate(constraint, Arrays.asList("abc", "abcdef"), false); evaluate(constraint, "ab", true); evaluate(constraint, "abcdefg", true); evaluate(constraint, Arrays.asList("abc", "abcdefg"), true); } @SuppressWarnings("unchecked") public void testListOfValuesConstraint() throws Exception { ListOfValuesConstraint constraint = new ListOfValuesConstraint(); try { constraint.setAllowedValues(Collections.emptyList()); } catch (DictionaryException e) { // expected checkI18NofExceptionMessage(e); } List allowedValues = Arrays.asList(new String[] {"abc", "def", "ghi"}); constraint.setAllowedValues(allowedValues); assertEquals("ListOfValuesConstraint type should be 'LIST'", "LIST", constraint.getType()); assertNotNull("ListOfValuesConstraint should have parameters", constraint.getParameters()); assertEquals("ListOfValuesConstraint should have 2 parameters", 2, constraint.getParameters().size()); assertEquals("caseSensitive should be true", Boolean.TRUE, constraint.getParameters().get("caseSensitive")); List allowedValuesParam = (List)constraint.getParameters().get("allowedValues"); assertEquals("Should be 3 allowable values", 3, allowedValuesParam.size()); assertEquals("First allowable value should be 'abc'", "abc", allowedValuesParam.get(0)); assertEquals("First allowable value should be 'def'", "def", allowedValuesParam.get(1)); assertEquals("First allowable value should be 'ghi'", "ghi", allowedValuesParam.get(2)); evaluate(constraint, "def", false); evaluate(constraint, "DEF", true); evaluate(constraint, Arrays.asList("abc", "def"), false); evaluate(constraint, Arrays.asList("abc", "DEF"), true); // now make it case-insensitive constraint.setCaseSensitive(false); assertEquals("caseSensitive should be false", Boolean.FALSE, constraint.getParameters().get("caseSensitive")); evaluate(constraint, "DEF", false); evaluate(constraint, Arrays.asList("abc", "DEF"), false); } public void testNumericRangeConstraint() throws Exception { NumericRangeConstraint constraint = new NumericRangeConstraint(); constraint.initialize(); assertEquals("NumericRangeConstraint type should be 'MINMAX'", "MINMAX", constraint.getType()); assertNotNull("NumericRangeConstraint should have parameters", constraint.getParameters()); assertEquals("NumericRangeConstraint should have 2 parameters", 2, constraint.getParameters().size()); // check that Double.MIN_VALUE and Double.MAX_VALUE are allowed by default constraint.evaluate(Double.MIN_VALUE); constraint.evaluate(Double.MAX_VALUE); // check that Double.NaN is not allowed by default evaluate(constraint, Double.NaN, true); // set some limits and check constraint.setMinValue(-5.0D); constraint.setMaxValue(+5.0D); constraint.initialize(); assertEquals("minValue should be -5", -5.0D, constraint.getParameters().get("minValue")); assertEquals("maxValue should be 5", 5.0D, constraint.getParameters().get("maxValue")); evaluate(constraint, "-1.0", false); evaluate(constraint, "+1.0", false); evaluate(constraint, Arrays.asList(-1, 0, 1), false); evaluate(constraint, "abc", true); evaluate(constraint, 56.453E4, true); evaluate(constraint, Arrays.asList(-1, 6), true); } public void testRegexConstraint() throws Exception { RegexConstraint constraint = new RegexConstraint(); constraint.setExpression("[A-Z]*"); constraint.setRequiresMatch(true); constraint.initialize(); assertEquals("RegexConstraint type should be 'REGEX'", "REGEX", constraint.getType()); assertNotNull("RegexConstraint should have parameters", constraint.getParameters()); assertEquals("RegexConstraint should have 2 parameters", 2, constraint.getParameters().size()); assertEquals("requiresMatch should be true", Boolean.TRUE, constraint.getParameters().get("requiresMatch")); assertEquals("expression should be [A-Z]*", "[A-Z]*", constraint.getParameters().get("expression")); // do some successful stuff evaluate(constraint, "ABC", false); evaluate(constraint, "DEF", false); // now some failures evaluate(constraint, "abc", true); // now a case of passing in an object that could be a string evaluate(constraint, DummyEnum.ABC, false); evaluate(constraint, DummyEnum.DEF, false); evaluate(constraint, DummyEnum.abc, true); // now switch the requiresMatch around constraint.setRequiresMatch(false); constraint.initialize(); assertEquals("requiresMatch should be false", Boolean.FALSE, constraint.getParameters().get("requiresMatch")); evaluate(constraint, DummyEnum.abc, false); } public void testRegexConstraintFilename() throws Exception { // we assume UTF-8 String expression = new String(".*[\\\"\\*\\\\\\>\\<\\?\\/\\:\\|\\¬\\£\\%\\&\\+\\;]+.*".getBytes("UTF-8")); String invalidChars = new String("\"*\\>.txt", true); // ... and a valid one evaluate(constraint, "Company Home", false); } private enum DummyEnum { ABC, DEF, abc; } private class DummyConstraint extends AbstractConstraint { private List tested; /* * @see org.alfresco.service.cmr.dictionary.Constraint#initialize() */ public void initialize() { tested = new ArrayList(4); } /** * Fails on everything but String values, which pass. * Null values cause runtime exceptions and all other failures are by * DictionaryException. */ @Override protected void evaluateSingleValue(Object value) { if (value == null) { throw new NullPointerException("Null value in dummy test"); } else if (value instanceof String) { tested.add(value); } else { throw new ConstraintException("Non-String value"); } } /* * @see org.alfresco.service.cmr.dictionary.Constraint#getParameters() */ public Map getParameters() { return null; } } }