TestConfigurationHelper.java
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.hadoop.util;
import java.util.Set;
import org.assertj.core.api.Assertions;
import org.assertj.core.api.IterableAssert;
import org.junit.Test;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.test.AbstractHadoopTestBase;
import static org.apache.hadoop.test.LambdaTestUtils.intercept;
import static org.apache.hadoop.util.ConfigurationHelper.ERROR_MULTIPLE_ELEMENTS_MATCHING_TO_LOWER_CASE_VALUE;
import static org.apache.hadoop.util.ConfigurationHelper.mapEnumNamesToValues;
import static org.apache.hadoop.util.ConfigurationHelper.parseEnumSet;
/**
* Test for {@link ConfigurationHelper}.
*/
public class TestConfigurationHelper extends AbstractHadoopTestBase {
/**
* Simple Enums.
* "i" is included for case tests, as it is special in turkey.
*/
private enum SimpleEnum { a, b, c, i }
/**
* Special case: an enum with no values.
*/
private enum EmptyEnum { }
/**
* Create assertion about the outcome of
* {@link ConfigurationHelper#parseEnumSet(String, String, Class, boolean)}.
* @param valueString value from Configuration
* @param enumClass class of enum
* @param ignoreUnknown should unknown values be ignored?
* @param <E> enum type
* @return an assertion on the outcome.
* @throws IllegalArgumentException if one of the entries was unknown and ignoreUnknown is false,
* or there are two entries in the enum which differ only by case.
*/
private static <E extends Enum<E>> IterableAssert<E> assertEnumParse(
final String valueString,
final Class<E> enumClass,
final boolean ignoreUnknown) {
final Set<E> enumSet = parseEnumSet("key", valueString, enumClass, ignoreUnknown);
final IterableAssert<E> assertion = Assertions.assertThat(enumSet);
return assertion.describedAs("parsed enum set '%s'", valueString);
}
/**
* Create a configuration with the key {@code key} set to a {@code value}.
* @param value value for the key
* @return a configuration with only key set.
*/
private Configuration confWithKey(String value) {
final Configuration conf = new Configuration(false);
conf.set("key", value);
return conf;
}
@Test
public void testEnumParseAll() {
assertEnumParse("*", SimpleEnum.class, false)
.containsExactly(SimpleEnum.a, SimpleEnum.b, SimpleEnum.c, SimpleEnum.i);
}
@Test
public void testEnumParse() {
assertEnumParse("a, b,c", SimpleEnum.class, false)
.containsExactly(SimpleEnum.a, SimpleEnum.b, SimpleEnum.c);
}
@Test
public void testEnumCaseIndependence() {
assertEnumParse("A, B, C, I", SimpleEnum.class, false)
.containsExactly(SimpleEnum.a, SimpleEnum.b, SimpleEnum.c, SimpleEnum.i);
}
@Test
public void testEmptyArguments() {
assertEnumParse(" ", SimpleEnum.class, false)
.isEmpty();
}
@Test
public void testUnknownEnumNotIgnored() throws Throwable {
intercept(IllegalArgumentException.class, "unrecognized", () ->
parseEnumSet("key", "c, unrecognized", SimpleEnum.class, false));
}
@Test
public void testUnknownEnumNotIgnoredThroughConf() throws Throwable {
intercept(IllegalArgumentException.class, "unrecognized", () ->
confWithKey("c, unrecognized")
.getEnumSet("key", SimpleEnum.class, false));
}
@Test
public void testUnknownEnumIgnored() {
assertEnumParse("c, d", SimpleEnum.class, true)
.containsExactly(SimpleEnum.c);
}
@Test
public void testUnknownStarEnum() throws Throwable {
intercept(IllegalArgumentException.class, "unrecognized", () ->
parseEnumSet("key", "*, unrecognized", SimpleEnum.class, false));
}
@Test
public void testUnknownStarEnumIgnored() {
assertEnumParse("*, d", SimpleEnum.class, true)
.containsExactly(SimpleEnum.a, SimpleEnum.b, SimpleEnum.c, SimpleEnum.i);
}
/**
* Unsupported enum as the same case value is present.
*/
private enum CaseConflictingEnum { a, A }
@Test
public void testCaseConflictingEnumNotSupported() throws Throwable {
intercept(IllegalArgumentException.class,
ERROR_MULTIPLE_ELEMENTS_MATCHING_TO_LOWER_CASE_VALUE,
() ->
parseEnumSet("key", "c, unrecognized",
CaseConflictingEnum.class, false));
}
@Test
public void testEmptyEnumMap() {
Assertions.assertThat(mapEnumNamesToValues("", EmptyEnum.class))
.isEmpty();
}
/**
* A star enum for an empty enum must be empty.
*/
@Test
public void testEmptyStarEnum() {
assertEnumParse("*", EmptyEnum.class, false)
.isEmpty();
}
@Test
public void testDuplicateValues() {
assertEnumParse("a, a, c, b, c", SimpleEnum.class, true)
.containsExactly(SimpleEnum.a, SimpleEnum.b, SimpleEnum.c);
}
}