/* * Copyright (C) 2005 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a * copy of the License at * * http://www.alfresco.org/legal/license.txt * * 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 org.alfresco.repo.dictionary.constraint; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; 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(); 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); 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); } 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); 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); evaluate(constraint, "DEF", false); evaluate(constraint, Arrays.asList("abc", "DEF"), false); } public void testNumericRangeConstraint() throws Exception { NumericRangeConstraint constraint = new NumericRangeConstraint(); constraint.initialize(); // 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(); 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(); // 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(); 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; 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"); } } } }