View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertFalse;
22  import static org.junit.Assert.assertTrue;
23  import static org.junit.Assert.fail;
24  
25  import java.io.IOException;
26  import java.util.Arrays;
27  import java.util.regex.Pattern;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.hadoop.hbase.client.Durability;
32  import org.apache.hadoop.hbase.exceptions.DeserializationException;
33  import org.apache.hadoop.hbase.testclassification.SmallTests;
34  import org.apache.hadoop.hbase.util.BuilderStyleTest;
35  import org.apache.hadoop.hbase.util.Bytes;
36  import org.junit.Test;
37  import org.junit.experimental.categories.Category;
38  
39  /**
40   * Test setting values in the descriptor
41   */
42  @Category(SmallTests.class)
43  public class TestHTableDescriptor {
44    final static Log LOG = LogFactory.getLog(TestHTableDescriptor.class);
45  
46    @Test
47    public void testPb() throws DeserializationException, IOException {
48      HTableDescriptor htd = new HTableDescriptor(HTableDescriptor.META_TABLEDESC);
49      final int v = 123;
50      htd.setMaxFileSize(v);
51      htd.setDurability(Durability.ASYNC_WAL);
52      htd.setReadOnly(true);
53      htd.setRegionReplication(2);
54      byte [] bytes = htd.toByteArray();
55      HTableDescriptor deserializedHtd = HTableDescriptor.parseFrom(bytes);
56      assertEquals(htd, deserializedHtd);
57      assertEquals(v, deserializedHtd.getMaxFileSize());
58      assertTrue(deserializedHtd.isReadOnly());
59      assertEquals(Durability.ASYNC_WAL, deserializedHtd.getDurability());
60      assertEquals(deserializedHtd.getRegionReplication(), 2);
61    }
62  
63    /**
64     * Test cps in the table description
65     * @throws Exception
66     */
67    @Test
68    public void testGetSetRemoveCP() throws Exception {
69      HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("table"));
70      // simple CP
71      String className = "org.apache.hadoop.hbase.coprocessor.BaseRegionObserver";
72      // add and check that it is present
73      desc.addCoprocessor(className);
74      assertTrue(desc.hasCoprocessor(className));
75      // remove it and check that it is gone
76      desc.removeCoprocessor(className);
77      assertFalse(desc.hasCoprocessor(className));
78    }
79  
80    /**
81     * Test cps in the table description
82     * @throws Exception
83     */
84    @Test
85    public void testSetListRemoveCP() throws Exception {
86      HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("testGetSetRemoveCP"));
87      // simple CP
88      String className1 = "org.apache.hadoop.hbase.coprocessor.BaseRegionObserver";
89      String className2 = "org.apache.hadoop.hbase.coprocessor.SampleRegionWALObserver";
90      // Check that any coprocessor is present.
91      assertTrue(desc.getCoprocessors().size() == 0);
92  
93      // Add the 1 coprocessor and check if present.
94      desc.addCoprocessor(className1);
95      assertTrue(desc.getCoprocessors().size() == 1);
96      assertTrue(desc.getCoprocessors().contains(className1));
97  
98      // Add the 2nd coprocessor and check if present.
99      // remove it and check that it is gone
100     desc.addCoprocessor(className2);
101     assertTrue(desc.getCoprocessors().size() == 2);
102     assertTrue(desc.getCoprocessors().contains(className2));
103 
104     // Remove one and check
105     desc.removeCoprocessor(className1);
106     assertTrue(desc.getCoprocessors().size() == 1);
107     assertFalse(desc.getCoprocessors().contains(className1));
108     assertTrue(desc.getCoprocessors().contains(className2));
109 
110     // Remove the last and check
111     desc.removeCoprocessor(className2);
112     assertTrue(desc.getCoprocessors().size() == 0);
113     assertFalse(desc.getCoprocessors().contains(className1));
114     assertFalse(desc.getCoprocessors().contains(className2));
115   }
116 
117   /**
118    * Test that we add and remove strings from settings properly.
119    * @throws Exception
120    */
121   @Test
122   public void testRemoveString() throws Exception {
123     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("table"));
124     String key = "Some";
125     String value = "value";
126     desc.setValue(key, value);
127     assertEquals(value, desc.getValue(key));
128     desc.remove(key);
129     assertEquals(null, desc.getValue(key));
130   }
131 
132   String legalTableNames[] = { "foo", "with-dash_under.dot", "_under_start_ok",
133       "with-dash.with_underscore", "02-01-2012.my_table_01-02", "xyz._mytable_", "9_9_0.table_02"
134       , "dot1.dot2.table", "new.-mytable", "with-dash.with.dot", "legal..t2", "legal..legal.t2",
135       "trailingdots..", "trailing.dots...", "ns:mytable", "ns:_mytable_", "ns:my_table_01-02",
136       "汉", "汉:字", "_字_", "foo:字", "foo.字", "字.foo"};
137   String illegalTableNames[] = { ".dot_start_illegal", "-dash_start_illegal", "spaces not ok",
138       "-dash-.start_illegal", "new.table with space", "01 .table", "ns:-illegaldash",
139       "new:.illegaldot", "new:illegalcolon1:", "new:illegalcolon1:2", String.valueOf((char)130),
140       String.valueOf((char)5), String.valueOf((char)65530)};
141 
142   @Test
143   public void testLegalHTableNames() {
144     for (String tn : legalTableNames) {
145       TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn));
146     }
147   }
148 
149   @Test
150   public void testIllegalHTableNames() {
151     for (String tn : illegalTableNames) {
152       try {
153         TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn));
154         fail("invalid tablename " + tn + " should have failed");
155       } catch (Exception e) {
156         // expected
157       }
158     }
159   }
160 
161   @Test
162   public void testLegalHTableNamesRegexWithBytes() {
163     for (String tn : legalTableNames) {
164       // valueOf(String) hits a different code-path than valueOf(byte[])
165       TableName tName = TableName.valueOf(Bytes.toBytes(tn));
166       assertTrue("Testing: '" + tn + "'", Pattern.matches(TableName.VALID_USER_TABLE_REGEX,
167           tName.getNameAsString()));
168     }
169   }
170 
171   @Test
172   public void testLegalHTableNamesRegex() {
173     for (String tn : legalTableNames) {
174       TableName tName = TableName.valueOf(tn);
175       assertTrue("Testing: '" + tn + "'", Pattern.matches(TableName.VALID_USER_TABLE_REGEX,
176           tName.getNameAsString()));
177     }
178   }
179 
180   @Test
181   public void testIllegalZooKeeperName() {
182     for (String name : Arrays.asList("zookeeper", "ns:zookeeper", "zookeeper:table")) {
183       try {
184         TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(name));
185         fail("invalid tablename " + name + " should have failed");
186       } catch (Exception e) {
187         // expected
188       }
189     }
190   }
191 
192   @Test
193   public void testIllegalHTableNamesRegex() {
194     for (String tn : illegalTableNames) {
195       LOG.info("Testing: '" + tn + "'");
196       assertFalse(Pattern.matches(TableName.VALID_USER_TABLE_REGEX, tn));
197     }
198   }
199 
200     /**
201    * Test default value handling for maxFileSize
202    */
203   @Test
204   public void testGetMaxFileSize() {
205     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("table"));
206     assertEquals(-1, desc.getMaxFileSize());
207     desc.setMaxFileSize(1111L);
208     assertEquals(1111L, desc.getMaxFileSize());
209   }
210 
211   /**
212    * Test default value handling for memStoreFlushSize
213    */
214   @Test
215   public void testGetMemStoreFlushSize() {
216     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("table"));
217     assertEquals(-1, desc.getMemStoreFlushSize());
218     desc.setMemStoreFlushSize(1111L);
219     assertEquals(1111L, desc.getMemStoreFlushSize());
220   }
221 
222   /**
223    * Test that we add and remove strings from configuration properly.
224    */
225   @Test
226   public void testAddGetRemoveConfiguration() throws Exception {
227     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("table"));
228     String key = "Some";
229     String value = "value";
230     desc.setConfiguration(key, value);
231     assertEquals(value, desc.getConfigurationValue(key));
232     desc.removeConfiguration(key);
233     assertEquals(null, desc.getConfigurationValue(key));
234   }
235 
236   @Test
237   public void testClassMethodsAreBuilderStyle() {
238     /* HTableDescriptor should have a builder style setup where setXXX/addXXX methods
239      * can be chainable together:
240      * . For example:
241      * HTableDescriptor htd
242      *   = new HTableDescriptor()
243      *     .setFoo(foo)
244      *     .setBar(bar)
245      *     .setBuz(buz)
246      *
247      * This test ensures that all methods starting with "set" returns the declaring object
248      */
249 
250     BuilderStyleTest.assertClassesAreBuilderStyle(HTableDescriptor.class);
251   }
252 
253   @Test
254   public void testModifyFamily() {
255     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("table"));
256     byte[] familyName = Bytes.toBytes("cf");
257     HColumnDescriptor hcd = new HColumnDescriptor(familyName);
258     hcd.setBlocksize(1000);
259     htd.addFamily(hcd);
260     assertEquals(1000, htd.getFamily(familyName).getBlocksize());
261     hcd = new HColumnDescriptor(familyName);
262     hcd.setBlocksize(2000);
263     htd.modifyFamily(hcd);
264     assertEquals(2000, htd.getFamily(familyName).getBlocksize());
265   }
266 
267   @Test(expected=IllegalArgumentException.class)
268   public void testModifyInexistentFamily() {
269     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("table"));
270     byte[] familyName = Bytes.toBytes("cf");
271     HColumnDescriptor hcd = new HColumnDescriptor(familyName);
272     htd.modifyFamily(hcd);
273   }
274 
275   @Test(expected=IllegalArgumentException.class)
276   public void testAddDuplicateFamilies() {
277     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("table"));
278     byte[] familyName = Bytes.toBytes("cf");
279     HColumnDescriptor hcd = new HColumnDescriptor(familyName);
280     hcd.setBlocksize(1000);
281     htd.addFamily(hcd);
282     assertEquals(1000, htd.getFamily(familyName).getBlocksize());
283     hcd = new HColumnDescriptor(familyName);
284     hcd.setBlocksize(2000);
285     htd.addFamily(hcd);
286   }
287 
288   @Test
289   public void testPriority() {
290     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("table"));
291     htd.setPriority(42);
292     assertEquals(42, htd.getPriority());
293   }
294 }