package io.eguan.configuration; /* * #%L * Project eguan * %% * Copyright (C) 2012 - 2017 Oodrive * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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. * #L% */ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import io.eguan.configuration.ValidationError.ErrorType; import java.io.ByteArrayInputStream; import java.io.IOException; import org.junit.Test; /** * Abstract class testing implementations of the abstract methods of {@link AbstractConfigKey} on subclasses. * * @author oodrive * @author pwehrle * */ public abstract class TestAbstractConfigKeys { /** * Specific enum used as type certain to be rejected by all correct {@link AbstractConfigKey#checkValue(Object)} and * {@link AbstractConfigKey#parseValue(String)} implementations. * * */ private static enum BadTypeEnum { /** * The constant no {@link AbstractConfigKey} should accept as value. */ NOT_YOUR_TYPE; } /** * Tests successful executions of {@link AbstractConfigKey#parseValue(String)} and * {@link AbstractConfigKey#valueToString(Object)} using the default value. * * @throws IllegalArgumentException * if the value is not parsable. Not part of this test. * @throws NullPointerException * if the value is {@code null}. Not part of this test. * @throws ConfigValidationException * @throws IOException */ @Test public final void testGetTypedValue() throws IllegalArgumentException, NullPointerException, IOException, ConfigValidationException { final AbstractConfigKey target = getTestKey(false, true); final Object defaultValue = target.getDefaultValue(); assertNotNull(defaultValue); final AbstractConfigurationContext testContext = new AbstractConfigurationContext("test.abstract.context", target) { }; final String inputString = testContext.getPropertyKey(target) + "=" + target.valueToString(defaultValue); final MetaConfiguration config = MetaConfiguration.newConfiguration( new ByteArrayInputStream(inputString.getBytes()), testContext); assertEquals(defaultValue, target.getTypedValue(config)); } /** * Tests successful executions of {@link AbstractConfigKey#parseValue(String)} and * {@link AbstractConfigKey#valueToString(Object)} using the default value. * * @throws IllegalArgumentException * if the value is not parsable. Not part of this test. * @throws NullPointerException * if the value is {@code null}. Not part of this test. */ @Test public final void testParseValueWithValueToString() throws IllegalArgumentException, NullPointerException { final AbstractConfigKey target = getTestKey(false, true); final Object defaultValue = target.getDefaultValue(); assertNotNull(defaultValue); final String defaultString = target.valueToString(defaultValue); final Object result = target.parseValue(defaultString); assertNotNull(result); assertEquals("parsed result is of same type as default value", defaultValue.getClass(), result.getClass()); assertEquals("parsed result has the same String value as initial default result", defaultString, target.valueToString(result)); } /** * Tests successful execution of {@link AbstractConfigKey#parseValue(String)} with an empty {@link String} as * parameter when the {@link AbstractConfigKey} does not have a default value. * * @throws IllegalArgumentException * if the value is not parsable. Considered a test failure. * @throws NullPointerException * if the value is {@code null}. Not part of this test. */ @Test public final void testParseValueEmptyString() { final AbstractConfigKey target = getTestKey(false, false); final Object value = target.parseValue(""); assertTrue((value == null) || ("".equals(value))); assertEquals("", target.valueToString(value)); } /** * Tests that when the value is an empty {@link String} and when the {@link AbstractConfigKey} has a default value, * the default value is returned. */ @Test public final void testParseValueEmptyDefaultString() { final AbstractConfigKey target = getTestKey(false, true); final Object value = target.parseValue(""); final Object defaultValue = target.getDefaultValue(); assertEquals(defaultValue, value); } /** * Tests failure of {@link AbstractConfigKey#parseValue(String)} due to a {@code null} parameter. * * @throws IllegalArgumentException * if the value is not parsable. Not part of this test. * @throws NullPointerException * if the value is {@code null}. Expected for this test. */ @Test(expected = NullPointerException.class) public final void testParseValueFailNull() throws IllegalArgumentException, NullPointerException { final AbstractConfigKey target = getTestKey(false, false); target.parseValue(null); } /** * Tests execution of {@link AbstractConfigKey#valueToString(Object)} with a {@code null} parameter. * * @throws IllegalArgumentException * if the value is not serializable. Not part of this test. */ @Test public final void testValueToStringNull() throws IllegalArgumentException { final AbstractConfigKey target = getTestKey(false, false); final String result = target.valueToString(null); assertEquals("", result); } /** * Tests failure of {@link AbstractConfigKey#valueToString(Object)} due to parameter of wrong type. * * @throws IllegalArgumentException * if the value is of the wrong type. Expected for this test. * @throws NullPointerException * if the value is {@code null}. Not part of this test. */ @Test(expected = IllegalArgumentException.class) public final void testValueToStringFailWrongType() { final AbstractConfigKey target = getTestKey(false, false); target.valueToString(BadTypeEnum.NOT_YOUR_TYPE); } /** * Tests failure of {@link AbstractConfigKey#checkValue(Object)} due to passing an object of bad type. */ @Test public final void testCheckValueFailWrongType() { final AbstractConfigKey target = getTestKey(false, false); final ValidationError result = target.checkValue(BadTypeEnum.NOT_YOUR_TYPE); assertEquals("validation result is ", ErrorType.VALUE_INVALID, result.getType()); assertEquals("validation result has empty context list", 0, result.getConfigurationContexts().length); assertEquals("validation result has right key", target, result.getConfigKeys()[0]); assertEquals("validation result has provided value", BadTypeEnum.NOT_YOUR_TYPE, result.getValue()); } /** * Tests failure of {@link AbstractConfigKey#checkValue(Object)} due to passing null to a * {@link AbstractConfigKey#isRequired() required} key. */ @Test public final void testCheckValueFailNullAndRequired() { final AbstractConfigKey target = getTestKey(true, false); assertTrue("value is required", target.isRequired()); assertFalse("has no default value", target.hasDefaultValue()); assertNull("default value is null", target.getDefaultValue()); final ValidationError result = target.checkValue(null); assertEquals("validation result is ", ErrorType.VALUE_REQUIRED, result.getType()); assertEquals("validation result has empty context list", 0, result.getConfigurationContexts().length); assertEquals("validation result has right key", target, result.getConfigKeys()[0]); assertNull("validation result has provided value", result.getValue()); } /** * Test successfully execution of {@link AbstractConfigKey#checkValue(Object)} given null on a key without default * value nor {@link AbstractConfigKey#isRequired() required} constraint. */ @Test public final void testCheckValueNullAndNotRequired() { final AbstractConfigKey target = getTestKey(false, false); assertFalse("value is not required", target.isRequired()); assertFalse("has no default value", target.hasDefaultValue()); assertNull("default value is null", target.getDefaultValue()); final ValidationError result = target.checkValue(null); assertEquals("validation produced no error", ValidationError.NO_ERROR, result); } /** * Test the {@link AbstractConfigKey#toString()} implementation for all extending classes. */ @Test public final void testToString() { final AbstractConfigKey target = getTestKey(false, false); assertEquals("toString returns class' canonical name", target.getClass().getCanonicalName(), target.toString()); } /** * Gets the {@link AbstractConfigKey key} to be tested. * * @param required * the value {@link AbstractConfigKey#isRequired()} on the resulting key will return * @param hasDefault * the value {@link AbstractConfigKey#hasDefaultValue()} on the resulting key will return * @return an instance of the {@link AbstractConfigKey} subclass to be tested */ protected abstract AbstractConfigKey getTestKey(boolean required, boolean hasDefault); }