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.regex.Pattern;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.apache.hadoop.hbase.client.Durability;
31  import org.apache.hadoop.hbase.exceptions.DeserializationException;
32  import org.apache.hadoop.hbase.testclassification.SmallTests;
33  import org.apache.hadoop.hbase.util.BuilderStyleTest;
34  import org.apache.hadoop.hbase.util.Bytes;
35  import org.junit.Test;
36  import org.junit.experimental.categories.Category;
37  
38  /**
39   * Test setting values in the descriptor
40   */
41  @Category(SmallTests.class)
42  public class TestHTableDescriptor {
43    private static final Log LOG = LogFactory.getLog(TestHTableDescriptor.class);
44  
45    @Test (expected=IOException.class)
46    public void testAddCoprocessorTwice() throws IOException {
47      HTableDescriptor htd = new HTableDescriptor(TableName.META_TABLE_NAME);
48      String cpName = "a.b.c.d";
49      htd.addCoprocessor(cpName);
50      htd.addCoprocessor(cpName);
51    }
52  
53    @Test
54    public void testAddCoprocessorWithSpecStr() throws IOException {
55      HTableDescriptor htd = new HTableDescriptor(TableName.META_TABLE_NAME);
56      String cpName = "a.b.c.d";
57      boolean expected = false;
58      try {
59        htd.addCoprocessorWithSpec(cpName);
60      } catch (IllegalArgumentException iae) {
61        expected = true;
62      }
63      if (!expected) fail();
64      // Try minimal spec.
65      try {
66        htd.addCoprocessorWithSpec("file:///some/path" + "|" + cpName);
67      } catch (IllegalArgumentException iae) {
68        expected = false;
69      }
70      if (expected) fail();
71      // Try more spec.
72      String spec = "hdfs:///foo.jar|com.foo.FooRegionObserver|1001|arg1=1,arg2=2";
73      try {
74        htd.addCoprocessorWithSpec(spec);
75      } catch (IllegalArgumentException iae) {
76        expected = false;
77      }
78      if (expected) fail();
79      // Try double add of same coprocessor
80      try {
81        htd.addCoprocessorWithSpec(spec);
82      } catch (IOException ioe) {
83        expected = true;
84      }
85      if (!expected) fail();
86    }
87  
88    @Test
89    public void testPb() throws DeserializationException, IOException {
90      HTableDescriptor htd = new HTableDescriptor(HTableDescriptor.META_TABLEDESC);
91      final int v = 123;
92      htd.setMaxFileSize(v);
93      htd.setDurability(Durability.ASYNC_WAL);
94      htd.setReadOnly(true);
95      htd.setRegionReplication(2);
96      byte [] bytes = htd.toByteArray();
97      HTableDescriptor deserializedHtd = HTableDescriptor.parseFrom(bytes);
98      assertEquals(htd, deserializedHtd);
99      assertEquals(v, deserializedHtd.getMaxFileSize());
100     assertTrue(deserializedHtd.isReadOnly());
101     assertEquals(Durability.ASYNC_WAL, deserializedHtd.getDurability());
102     assertEquals(deserializedHtd.getRegionReplication(), 2);
103   }
104 
105   /**
106    * Test cps in the table description
107    * @throws Exception
108    */
109   @Test
110   public void testGetSetRemoveCP() throws Exception {
111     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("table"));
112     // simple CP
113     String className = "org.apache.hadoop.hbase.coprocessor.BaseRegionObserver";
114     // add and check that it is present
115     desc.addCoprocessor(className);
116     assertTrue(desc.hasCoprocessor(className));
117     // remove it and check that it is gone
118     desc.removeCoprocessor(className);
119     assertFalse(desc.hasCoprocessor(className));
120   }
121 
122   /**
123    * Test cps in the table description
124    * @throws Exception
125    */
126   @Test
127   public void testSetListRemoveCP() throws Exception {
128     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("testGetSetRemoveCP"));
129     // simple CP
130     String className1 = "org.apache.hadoop.hbase.coprocessor.BaseRegionObserver";
131     String className2 = "org.apache.hadoop.hbase.coprocessor.SampleRegionWALObserver";
132     // Check that any coprocessor is present.
133     assertTrue(desc.getCoprocessors().size() == 0);
134 
135     // Add the 1 coprocessor and check if present.
136     desc.addCoprocessor(className1);
137     assertTrue(desc.getCoprocessors().size() == 1);
138     assertTrue(desc.getCoprocessors().contains(className1));
139 
140     // Add the 2nd coprocessor and check if present.
141     // remove it and check that it is gone
142     desc.addCoprocessor(className2);
143     assertTrue(desc.getCoprocessors().size() == 2);
144     assertTrue(desc.getCoprocessors().contains(className2));
145 
146     // Remove one and check
147     desc.removeCoprocessor(className1);
148     assertTrue(desc.getCoprocessors().size() == 1);
149     assertFalse(desc.getCoprocessors().contains(className1));
150     assertTrue(desc.getCoprocessors().contains(className2));
151 
152     // Remove the last and check
153     desc.removeCoprocessor(className2);
154     assertTrue(desc.getCoprocessors().size() == 0);
155     assertFalse(desc.getCoprocessors().contains(className1));
156     assertFalse(desc.getCoprocessors().contains(className2));
157   }
158 
159   /**
160    * Test that we add and remove strings from settings properly.
161    * @throws Exception
162    */
163   @Test
164   public void testRemoveString() throws Exception {
165     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("table"));
166     String key = "Some";
167     String value = "value";
168     desc.setValue(key, value);
169     assertEquals(value, desc.getValue(key));
170     desc.remove(key);
171     assertEquals(null, desc.getValue(key));
172   }
173 
174   String legalTableNames[] = { "foo", "with-dash_under.dot", "_under_start_ok",
175       "with-dash.with_underscore", "02-01-2012.my_table_01-02", "xyz._mytable_", "9_9_0.table_02"
176       , "dot1.dot2.table", "new.-mytable", "with-dash.with.dot", "legal..t2", "legal..legal.t2",
177       "trailingdots..", "trailing.dots...", "ns:mytable", "ns:_mytable_", "ns:my_table_01-02"};
178   String illegalTableNames[] = { ".dot_start_illegal", "-dash_start_illegal", "spaces not ok",
179       "-dash-.start_illegal", "new.table with space", "01 .table", "ns:-illegaldash",
180       "new:.illegaldot", "new:illegalcolon1:", "new:illegalcolon1:2"};
181 
182   @Test
183   public void testLegalHTableNames() {
184     for (String tn : legalTableNames) {
185       TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn));
186     }
187   }
188 
189   @Test
190   public void testIllegalHTableNames() {
191     for (String tn : illegalTableNames) {
192       try {
193         TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn));
194         fail("invalid tablename " + tn + " should have failed");
195       } catch (Exception e) {
196         // expected
197       }
198     }
199   }
200 
201   @Test
202   public void testLegalHTableNamesRegex() {
203     for (String tn : legalTableNames) {
204       TableName tName = TableName.valueOf(tn);
205       assertTrue("Testing: '" + tn + "'", Pattern.matches(TableName.VALID_USER_TABLE_REGEX,
206           tName.getNameAsString()));
207     }
208   }
209 
210   @Test
211   public void testIllegalHTableNamesRegex() {
212     for (String tn : illegalTableNames) {
213       LOG.info("Testing: '" + tn + "'");
214       assertFalse(Pattern.matches(TableName.VALID_USER_TABLE_REGEX, tn));
215     }
216   }
217 
218     /**
219    * Test default value handling for maxFileSize
220    */
221   @Test
222   public void testGetMaxFileSize() {
223     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("table"));
224     assertEquals(-1, desc.getMaxFileSize());
225     desc.setMaxFileSize(1111L);
226     assertEquals(1111L, desc.getMaxFileSize());
227   }
228 
229   /**
230    * Test default value handling for memStoreFlushSize
231    */
232   @Test
233   public void testGetMemStoreFlushSize() {
234     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("table"));
235     assertEquals(-1, desc.getMemStoreFlushSize());
236     desc.setMemStoreFlushSize(1111L);
237     assertEquals(1111L, desc.getMemStoreFlushSize());
238   }
239 
240   /**
241    * Test that we add and remove strings from configuration properly.
242    */
243   @Test
244   public void testAddGetRemoveConfiguration() throws Exception {
245     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("table"));
246     String key = "Some";
247     String value = "value";
248     desc.setConfiguration(key, value);
249     assertEquals(value, desc.getConfigurationValue(key));
250     desc.removeConfiguration(key);
251     assertEquals(null, desc.getConfigurationValue(key));
252   }
253 
254   @Test
255   public void testClassMethodsAreBuilderStyle() {
256     /* HTableDescriptor should have a builder style setup where setXXX/addXXX methods
257      * can be chainable together:
258      * . For example:
259      * HTableDescriptor htd
260      *   = new HTableDescriptor()
261      *     .setFoo(foo)
262      *     .setBar(bar)
263      *     .setBuz(buz)
264      *
265      * This test ensures that all methods starting with "set" returns the declaring object
266      */
267 
268     BuilderStyleTest.assertClassesAreBuilderStyle(HTableDescriptor.class);
269   }
270 
271   @Test
272   public void testModifyFamily() {
273     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("table"));
274     byte[] familyName = Bytes.toBytes("cf");
275     HColumnDescriptor hcd = new HColumnDescriptor(familyName);
276     hcd.setBlocksize(1000);
277     hcd.setDFSReplication((short) 3);
278     htd.addFamily(hcd);
279     assertEquals(1000, htd.getFamily(familyName).getBlocksize());
280     assertEquals(3, htd.getFamily(familyName).getDFSReplication());
281     hcd = new HColumnDescriptor(familyName);
282     hcd.setBlocksize(2000);
283     hcd.setDFSReplication((short) 1);
284     htd.modifyFamily(hcd);
285     assertEquals(2000, htd.getFamily(familyName).getBlocksize());
286     assertEquals(1, htd.getFamily(familyName).getDFSReplication());
287   }
288 
289   @Test(expected=IllegalArgumentException.class)
290   public void testModifyInexistentFamily() {
291     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("table"));
292     byte[] familyName = Bytes.toBytes("cf");
293     HColumnDescriptor hcd = new HColumnDescriptor(familyName);
294     htd.modifyFamily(hcd);
295   }
296 
297   @Test(expected=IllegalArgumentException.class)
298   public void testAddDuplicateFamilies() {
299     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("table"));
300     byte[] familyName = Bytes.toBytes("cf");
301     HColumnDescriptor hcd = new HColumnDescriptor(familyName);
302     hcd.setBlocksize(1000);
303     htd.addFamily(hcd);
304     assertEquals(1000, htd.getFamily(familyName).getBlocksize());
305     hcd = new HColumnDescriptor(familyName);
306     hcd.setBlocksize(2000);
307     htd.addFamily(hcd);
308   }
309 }