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; 019 020import static org.junit.jupiter.api.Assertions.assertEquals; 021import static org.junit.jupiter.api.Assertions.assertNull; 022import static org.junit.jupiter.api.Assertions.assertThrows; 023 024import java.util.HashMap; 025import java.util.Map; 026import org.apache.hadoop.conf.Configuration; 027import org.apache.hadoop.hbase.testclassification.MiscTests; 028import org.apache.hadoop.hbase.testclassification.SmallTests; 029import org.apache.hadoop.hbase.util.Bytes; 030import org.junit.jupiter.api.BeforeEach; 031import org.junit.jupiter.api.Tag; 032import org.junit.jupiter.api.Test; 033 034@Tag(MiscTests.TAG) 035@Tag(SmallTests.TAG) 036public class TestCompoundConfiguration { 037 038 private Configuration baseConf; 039 private int baseConfSize; 040 041 @BeforeEach 042 public void setUp() throws Exception { 043 baseConf = new Configuration(); 044 baseConf.set("A", "1"); 045 baseConf.setInt("B", 2); 046 baseConf.set("C", "3"); 047 baseConfSize = baseConf.size(); 048 } 049 050 @Test 051 public void testBasicFunctionality() throws ClassNotFoundException { 052 CompoundConfiguration compoundConf = new CompoundConfiguration().add(baseConf); 053 assertEquals("1", compoundConf.get("A")); 054 assertEquals(2, compoundConf.getInt("B", 0)); 055 assertEquals(3, compoundConf.getInt("C", 0)); 056 assertEquals(0, compoundConf.getInt("D", 0)); 057 058 assertEquals(CompoundConfiguration.class, 059 compoundConf.getClassByName(CompoundConfiguration.class.getName())); 060 assertThrows(ClassNotFoundException.class, () -> compoundConf.getClassByName("bad_class_name"), 061 "Trying to load bad_class_name should throw an exception"); 062 } 063 064 @Test 065 public void testPut() { 066 CompoundConfiguration compoundConf = new CompoundConfiguration().add(baseConf); 067 assertEquals("1", compoundConf.get("A")); 068 assertEquals(2, compoundConf.getInt("B", 0)); 069 assertEquals(3, compoundConf.getInt("C", 0)); 070 assertEquals(0, compoundConf.getInt("D", 0)); 071 072 compoundConf.set("A", "1337"); 073 compoundConf.set("string", "stringvalue"); 074 assertEquals(1337, compoundConf.getInt("A", 0)); 075 assertEquals("stringvalue", compoundConf.get("string")); 076 077 // we didn't modify the base conf 078 assertEquals("1", baseConf.get("A")); 079 assertNull(baseConf.get("string")); 080 081 // adding to the base shows up in the compound 082 baseConf.set("setInParent", "fromParent"); 083 assertEquals("fromParent", compoundConf.get("setInParent")); 084 } 085 086 @Test 087 public void testWithConfig() { 088 Configuration conf = new Configuration(); 089 conf.set("B", "2b"); 090 conf.set("C", "33"); 091 conf.set("D", "4"); 092 093 CompoundConfiguration compoundConf = new CompoundConfiguration().add(baseConf).add(conf); 094 assertEquals("1", compoundConf.get("A")); 095 assertEquals("2b", compoundConf.get("B")); 096 assertEquals(33, compoundConf.getInt("C", 0)); 097 assertEquals("4", compoundConf.get("D")); 098 assertEquals(4, compoundConf.getInt("D", 0)); 099 assertNull(compoundConf.get("E")); 100 assertEquals(6, compoundConf.getInt("F", 6)); 101 102 int cnt = 0; 103 for (Map.Entry<String, String> entry : compoundConf) { 104 cnt++; 105 if (entry.getKey().equals("B")) { 106 assertEquals("2b", entry.getValue()); 107 } else if (entry.getKey().equals("G")) { 108 assertNull(entry.getValue()); 109 } 110 } 111 // verify that entries from ImmutableConfigMap's are merged in the iterator's view 112 assertEquals(baseConfSize + 1, cnt); 113 } 114 115 private Bytes strToIb(String s) { 116 return new Bytes(Bytes.toBytes(s)); 117 } 118 119 @Test 120 public void testWithIbwMap() { 121 Map<Bytes, Bytes> map = new HashMap<>(); 122 map.put(strToIb("B"), strToIb("2b")); 123 map.put(strToIb("C"), strToIb("33")); 124 map.put(strToIb("D"), strToIb("4")); 125 // unlike config, note that IBW Maps can accept null values 126 map.put(strToIb("G"), null); 127 128 CompoundConfiguration compoundConf = new CompoundConfiguration().add(baseConf).addBytesMap(map); 129 assertEquals("1", compoundConf.get("A")); 130 assertEquals("2b", compoundConf.get("B")); 131 assertEquals(33, compoundConf.getInt("C", 0)); 132 assertEquals("4", compoundConf.get("D")); 133 assertEquals(4, compoundConf.getInt("D", 0)); 134 assertNull(compoundConf.get("E")); 135 assertEquals(6, compoundConf.getInt("F", 6)); 136 assertNull(compoundConf.get("G")); 137 138 int cnt = 0; 139 for (Map.Entry<String, String> entry : compoundConf) { 140 cnt++; 141 if (entry.getKey().equals("B")) { 142 assertEquals("2b", entry.getValue()); 143 } else if (entry.getKey().equals("G")) { 144 assertNull(entry.getValue()); 145 } 146 } 147 // verify that entries from ImmutableConfigMap's are merged in the iterator's view 148 assertEquals(baseConfSize + 2, cnt); 149 150 // Verify that adding map after compound configuration is modified overrides properly 151 CompoundConfiguration conf2 = new CompoundConfiguration(); 152 conf2.set("X", "modification"); 153 conf2.set("D", "not4"); 154 assertEquals("modification", conf2.get("X")); 155 assertEquals("not4", conf2.get("D")); 156 conf2.addBytesMap(map); 157 assertEquals("4", conf2.get("D")); // map overrides 158 } 159 160 @Test 161 public void testWithStringMap() { 162 Map<String, String> map = new HashMap<>(); 163 map.put("B", "2b"); 164 map.put("C", "33"); 165 map.put("D", "4"); 166 // unlike config, note that IBW Maps can accept null values 167 map.put("G", null); 168 169 CompoundConfiguration compoundConf = new CompoundConfiguration().addStringMap(map); 170 assertEquals("2b", compoundConf.get("B")); 171 assertEquals(33, compoundConf.getInt("C", 0)); 172 assertEquals("4", compoundConf.get("D")); 173 assertEquals(4, compoundConf.getInt("D", 0)); 174 assertNull(compoundConf.get("E")); 175 assertEquals(6, compoundConf.getInt("F", 6)); 176 assertNull(compoundConf.get("G")); 177 178 int cnt = 0; 179 for (Map.Entry<String, String> entry : compoundConf) { 180 cnt++; 181 if (entry.getKey().equals("B")) { 182 assertEquals("2b", entry.getValue()); 183 } else if (entry.getKey().equals("G")) { 184 assertNull(entry.getValue()); 185 } 186 } 187 // verify that entries from ImmutableConfigMap's are merged in the iterator's view 188 assertEquals(4, cnt); 189 190 // Verify that adding map after compound configuration is modified overrides properly 191 CompoundConfiguration conf2 = new CompoundConfiguration(); 192 conf2.set("X", "modification"); 193 conf2.set("D", "not4"); 194 assertEquals("modification", conf2.get("X")); 195 assertEquals("not4", conf2.get("D")); 196 conf2.addStringMap(map); 197 assertEquals("4", conf2.get("D")); // map overrides 198 } 199 200 @Test 201 public void testLaterConfigsOverrideEarlier() { 202 Map<String, String> map1 = new HashMap<>(); 203 map1.put("A", "2"); 204 map1.put("D", "5"); 205 Map<String, String> map2 = new HashMap<>(); 206 String newValueForA = "3", newValueForB = "4"; 207 map2.put("A", newValueForA); 208 map2.put("B", newValueForB); 209 210 CompoundConfiguration compoundConf = 211 new CompoundConfiguration().addStringMap(map1).add(baseConf); 212 assertEquals("1", compoundConf.get("A")); 213 assertEquals("5", compoundConf.get("D")); 214 compoundConf.addStringMap(map2); 215 assertEquals(newValueForA, compoundConf.get("A")); 216 assertEquals(newValueForB, compoundConf.get("B")); 217 assertEquals("5", compoundConf.get("D")); 218 219 int cnt = 0; 220 for (Map.Entry<String, String> entry : compoundConf) { 221 cnt++; 222 if (entry.getKey().equals("A")) { 223 assertEquals(newValueForA, entry.getValue()); 224 } else if (entry.getKey().equals("B")) { 225 assertEquals(newValueForB, entry.getValue()); 226 } 227 } 228 // verify that entries from ImmutableConfigMap's are merged in the iterator's view 229 assertEquals(baseConfSize + 1, cnt); 230 } 231}