001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.conf;
019
020import static org.junit.Assert.fail;
021
022import java.util.UUID;
023import java.util.function.Consumer;
024import org.apache.hadoop.conf.Configuration;
025import org.apache.hadoop.hbase.CompoundConfiguration;
026import org.apache.hadoop.hbase.HBaseClassTestRule;
027import org.apache.hadoop.hbase.testclassification.MiscTests;
028import org.apache.hadoop.hbase.testclassification.SmallTests;
029import org.junit.ClassRule;
030import org.junit.Test;
031import org.junit.experimental.categories.Category;
032
033@Category({ MiscTests.class, SmallTests.class })
034public class TestConfigKey {
035  @ClassRule
036  public static final HBaseClassTestRule CLASS_RULE =
037    HBaseClassTestRule.forClass(TestConfigKey.class);
038
039  private interface Interface {
040  }
041
042  private class Class implements Interface {
043  }
044
045  private void assertThrows(Runnable r) {
046    try {
047      r.run();
048      fail("validation should have failed");
049    } catch (IllegalArgumentException e) {
050      // Expected
051    }
052  }
053
054  private void assertPasses(Configuration conf, Consumer<Configuration> block) {
055    Configuration copy = new CompoundConfiguration().add(conf);
056    block.accept(copy);
057    ConfigKey.validate(copy);
058  }
059
060  private void assertThrows(Configuration conf, Consumer<Configuration> block) {
061    Configuration copy = new CompoundConfiguration().add(conf);
062    block.accept(copy);
063    assertThrows(() -> ConfigKey.validate(copy));
064  }
065
066  @Test
067  public void testConfigKey() {
068    Configuration conf = new CompoundConfiguration();
069
070    String intKey = UUID.randomUUID().toString();
071    ConfigKey.INT(intKey);
072    conf.set(intKey, "1");
073
074    String longKey = UUID.randomUUID().toString();
075    ConfigKey.LONG(longKey);
076    conf.set(longKey, "1");
077
078    String floatKey = UUID.randomUUID().toString();
079    ConfigKey.FLOAT(floatKey);
080    conf.set(floatKey, "1.0");
081
082    String doubleKey = UUID.randomUUID().toString();
083    ConfigKey.DOUBLE(doubleKey);
084    conf.set(doubleKey, "1.0");
085
086    String classKey = UUID.randomUUID().toString();
087    ConfigKey.CLASS(classKey, Interface.class);
088    conf.set(classKey, Class.class.getName());
089
090    String booleanKey = UUID.randomUUID().toString();
091    ConfigKey.BOOLEAN(booleanKey);
092    conf.set(booleanKey, "true");
093
094    // This should pass
095    ConfigKey.validate(conf);
096
097    // Add a predicate to make the validation fail
098    ConfigKey.INT(intKey, i -> i < 0);
099    assertThrows(() -> ConfigKey.validate(conf));
100
101    // New predicates to make the validation pass
102    ConfigKey.INT(intKey, i -> i > 0, i -> i < 2);
103    ConfigKey.validate(conf);
104
105    // Remove the predicate
106    ConfigKey.INT(intKey);
107
108    // Passing examples
109    assertPasses(conf, copy -> copy.set(intKey, String.valueOf(Integer.MAX_VALUE)));
110    assertPasses(conf, copy -> copy.set(longKey, String.valueOf(Long.MAX_VALUE)));
111    assertPasses(conf, copy -> copy.set(floatKey, String.valueOf(Float.MAX_VALUE)));
112    assertPasses(conf, copy -> copy.set(doubleKey, String.valueOf(Double.MAX_VALUE)));
113
114    // Because Configuration#getBoolean doesn't throw an exception on invalid values, we don't
115    // validate the value here
116    assertPasses(conf, copy -> copy.set(booleanKey, "yeah?"));
117
118    // Failing examples
119    assertThrows(conf, copy -> copy.set(intKey, "x"));
120    assertThrows(conf, copy -> copy.set(longKey, Long.MAX_VALUE + "0"));
121    assertThrows(conf, copy -> copy.set(longKey, "x"));
122    assertThrows(conf, copy -> copy.set(floatKey, "x"));
123    assertThrows(conf, copy -> copy.set(doubleKey, "x"));
124    assertThrows(conf, copy -> copy.set(classKey, "NoSuchClass"));
125    assertThrows(conf, copy -> copy.set(classKey, getClass().getName()));
126  }
127}