1   /**
2    * Copyright The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.regionserver;
21  
22  import java.util.HashMap;
23  import java.util.Map;
24  
25  import org.apache.hadoop.conf.Configuration;
26  import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
27  import org.apache.hadoop.hbase.regionserver.CompoundConfiguration;
28  import org.apache.hadoop.hbase.util.Bytes;
29  import org.apache.hadoop.hbase.SmallTests;
30  
31  import org.junit.experimental.categories.Category;
32  import org.junit.Test;
33  
34  import junit.framework.TestCase;
35  
36  @Category(SmallTests.class)
37  public class TestCompoundConfiguration extends TestCase {
38    private Configuration baseConf;
39    private int baseConfSize;
40  
41    @Override
42    protected void setUp() throws Exception {
43      baseConf = new Configuration();
44      baseConf.set("A", "1");
45      baseConf.setInt("B", 2);
46      baseConf.set("C", "3");
47      baseConfSize = baseConf.size();
48    }
49  
50    @Test
51    public void testBasicFunctionality() throws ClassNotFoundException {
52      CompoundConfiguration compoundConf = new CompoundConfiguration()
53          .add(baseConf); 
54      assertEquals("1", compoundConf.get("A"));
55      assertEquals(2, compoundConf.getInt("B", 0));
56      assertEquals(3, compoundConf.getInt("C", 0));
57      assertEquals(0, compoundConf.getInt("D", 0));
58  
59      assertEquals(CompoundConfiguration.class, compoundConf
60          .getClassByName(CompoundConfiguration.class.getName()));
61      try {
62        compoundConf.getClassByName("bad_class_name");
63        fail("Trying to load bad_class_name should throw an exception");
64      } catch (ClassNotFoundException e) {
65        // win!
66      }
67    }
68  
69    @Test
70    public void testPut() {
71      CompoundConfiguration compoundConf = new CompoundConfiguration()
72        .add(baseConf);
73      assertEquals("1", compoundConf.get("A"));
74      assertEquals(2, compoundConf.getInt("B", 0));
75      assertEquals(3, compoundConf.getInt("C", 0));
76      assertEquals(0, compoundConf.getInt("D", 0));
77  
78      compoundConf.set("A", "1337");
79      compoundConf.set("string", "stringvalue");
80      assertEquals(1337, compoundConf.getInt("A", 0));
81      assertEquals("stringvalue", compoundConf.get("string"));
82  
83      // we didn't modify the base conf
84      assertEquals("1", baseConf.get("A"));
85      assertNull(baseConf.get("string"));
86  
87      // adding to the base shows up in the compound
88      baseConf.set("setInParent", "fromParent");
89      assertEquals("fromParent", compoundConf.get("setInParent"));
90    }
91  
92    @Test
93    public void testWithConfig() {
94      Configuration conf = new Configuration();
95      conf.set("B", "2b");
96      conf.set("C", "33");
97      conf.set("D", "4");
98  
99      CompoundConfiguration compoundConf = new CompoundConfiguration()
100         .add(baseConf)
101         .add(conf);
102     assertEquals("1", compoundConf.get("A"));
103     assertEquals("2b", compoundConf.get("B"));
104     assertEquals(33, compoundConf.getInt("C", 0));
105     assertEquals("4", compoundConf.get("D"));
106     assertEquals(4, compoundConf.getInt("D", 0));
107     assertNull(compoundConf.get("E"));
108     assertEquals(6, compoundConf.getInt("F", 6));
109 
110     int cnt = 0;
111     for (Map.Entry<String,String> entry : compoundConf) {
112       cnt++;
113       if (entry.getKey().equals("B")) assertEquals("2b", entry.getValue());
114       else if (entry.getKey().equals("G")) assertEquals(null, entry.getValue());
115     }
116     // verify that entries from ImmutableConfigMap's are merged in the iterator's view
117     assertEquals(baseConfSize + 1, cnt);
118   }
119 
120   private ImmutableBytesWritable strToIbw(String s) {
121     return new ImmutableBytesWritable(Bytes.toBytes(s));
122   }
123 
124   @Test
125   public void testWithIbwMap() {
126     Map<ImmutableBytesWritable, ImmutableBytesWritable> map =
127       new HashMap<ImmutableBytesWritable, ImmutableBytesWritable>();
128     map.put(strToIbw("B"), strToIbw("2b"));
129     map.put(strToIbw("C"), strToIbw("33"));
130     map.put(strToIbw("D"), strToIbw("4"));
131     // unlike config, note that IBW Maps can accept null values
132     map.put(strToIbw("G"), null);
133 
134     CompoundConfiguration compoundConf = new CompoundConfiguration()
135       .add(baseConf)
136       .add(map);
137     assertEquals("1", compoundConf.get("A"));
138     assertEquals("2b", compoundConf.get("B"));
139     assertEquals(33, compoundConf.getInt("C", 0));
140     assertEquals("4", compoundConf.get("D"));
141     assertEquals(4, compoundConf.getInt("D", 0));
142     assertNull(compoundConf.get("E"));
143     assertEquals(6, compoundConf.getInt("F", 6));
144     assertNull(compoundConf.get("G"));
145 
146     int cnt = 0;
147     for (Map.Entry<String,String> entry : compoundConf) {
148       cnt++;
149       if (entry.getKey().equals("B")) assertEquals("2b", entry.getValue());
150       else if (entry.getKey().equals("G")) assertEquals(null, entry.getValue());
151     }
152     // verify that entries from ImmutableConfigMap's are merged in the iterator's view
153     assertEquals(baseConfSize + 2, cnt);
154 
155     // Verify that adding map after compound configuration is modified overrides properly
156     CompoundConfiguration conf2 = new CompoundConfiguration();
157     conf2.set("X", "modification");
158     conf2.set("D", "not4");
159     assertEquals("modification", conf2.get("X"));
160     assertEquals("not4", conf2.get("D"));
161     conf2.add(map);
162     assertEquals("4", conf2.get("D")); // map overrides
163   }
164 
165   @Test
166   public void testWithStringMap() {
167     Map<String, String> map = new HashMap<String, String>();
168     map.put("B", "2b");
169     map.put("C", "33");
170     map.put("D", "4");
171     // unlike config, note that IBW Maps can accept null values
172     map.put("G", null);
173 
174     CompoundConfiguration compoundConf = new CompoundConfiguration().addStringMap(map);
175     assertEquals("2b", compoundConf.get("B"));
176     assertEquals(33, compoundConf.getInt("C", 0));
177     assertEquals("4", compoundConf.get("D"));
178     assertEquals(4, compoundConf.getInt("D", 0));
179     assertNull(compoundConf.get("E"));
180     assertEquals(6, compoundConf.getInt("F", 6));
181     assertNull(compoundConf.get("G"));
182 
183     int cnt = 0;
184     for (Map.Entry<String,String> entry : compoundConf) {
185       cnt++;
186       if (entry.getKey().equals("B")) assertEquals("2b", entry.getValue());
187       else if (entry.getKey().equals("G")) assertEquals(null, entry.getValue());
188     }
189     // verify that entries from ImmutableConfigMap's are merged in the iterator's view
190     assertEquals(4, cnt);
191     
192     // Verify that adding map after compound configuration is modified overrides properly
193     CompoundConfiguration conf2 = new CompoundConfiguration();
194     conf2.set("X", "modification");
195     conf2.set("D", "not4");
196     assertEquals("modification", conf2.get("X"));
197     assertEquals("not4", conf2.get("D"));
198     conf2.addStringMap(map);
199     assertEquals("4", conf2.get("D")); // map overrides
200   }
201 
202   @Test
203   public void testLaterConfigsOverrideEarlier() {
204     Configuration map1 = new Configuration(false);
205     map1.set("A", "2");
206     map1.set("D", "5");
207     Configuration map2 = new Configuration(false);
208     String newValueForA = "3", newValueForB = "4";
209     map2.set("A", newValueForA);
210     map2.set("B", newValueForB);
211 
212     CompoundConfiguration compoundConf = new CompoundConfiguration()
213       .add(map1).add(baseConf);
214     assertEquals("1", compoundConf.get("A"));
215     assertEquals("5", compoundConf.get("D"));
216     compoundConf.add(map2);
217     assertEquals(newValueForA, compoundConf.get("A"));
218     assertEquals(newValueForB, compoundConf.get("B"));
219     assertEquals("5", compoundConf.get("D"));
220 
221     int cnt = 0;
222     for (Map.Entry<String,String> entry : compoundConf) {
223       cnt++;
224       if (entry.getKey().equals("A")) assertEquals(newValueForA, entry.getValue());
225       else if (entry.getKey().equals("B")) assertEquals(newValueForB, entry.getValue());
226     }
227     // verify that entries from ImmutableConfigMap's are merged in the iterator's view
228     assertEquals(baseConfSize + 1, cnt);
229   }
230 
231   @org.junit.Rule
232   public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu =
233     new org.apache.hadoop.hbase.ResourceCheckerJUnitRule();
234 }