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.Assert.assertEquals; 021import static org.junit.Assert.assertFalse; 022import static org.junit.Assert.assertTrue; 023import static org.junit.Assert.fail; 024 025import java.io.IOException; 026import java.util.Arrays; 027import java.util.regex.Pattern; 028 029import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 030import org.apache.hadoop.hbase.client.Durability; 031import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 032import org.apache.hadoop.hbase.exceptions.DeserializationException; 033import org.apache.hadoop.hbase.testclassification.MiscTests; 034import org.apache.hadoop.hbase.testclassification.SmallTests; 035import org.apache.hadoop.hbase.util.BuilderStyleTest; 036import org.apache.hadoop.hbase.util.Bytes; 037import org.junit.ClassRule; 038import org.junit.Rule; 039import org.junit.Test; 040import org.junit.experimental.categories.Category; 041import org.junit.rules.TestName; 042import org.slf4j.Logger; 043import org.slf4j.LoggerFactory; 044 045/** 046 * Test setting values in the descriptor 047 * 048 * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 together with 049 * {@link HTableDescriptor}. 050 */ 051@Category({MiscTests.class, SmallTests.class}) 052@Deprecated 053public class TestHTableDescriptor { 054 055 @ClassRule 056 public static final HBaseClassTestRule CLASS_RULE = 057 HBaseClassTestRule.forClass(TestHTableDescriptor.class); 058 059 private static final Logger LOG = LoggerFactory.getLogger(TestHTableDescriptor.class); 060 061 @Rule 062 public TestName name = new TestName(); 063 064 @Test (expected=IOException.class) 065 public void testAddCoprocessorTwice() throws IOException { 066 HTableDescriptor htd = new HTableDescriptor(TableName.META_TABLE_NAME); 067 String cpName = "a.b.c.d"; 068 htd.addCoprocessor(cpName); 069 htd.addCoprocessor(cpName); 070 } 071 072 @Test 073 public void testAddCoprocessorWithSpecStr() throws IOException { 074 HTableDescriptor htd = new HTableDescriptor(TableName.META_TABLE_NAME); 075 String cpName = "a.b.c.d"; 076 try { 077 htd.addCoprocessorWithSpec(cpName); 078 fail(); 079 } catch (IllegalArgumentException iae) { 080 // Expected as cpName is invalid 081 } 082 083 // Try minimal spec. 084 try { 085 htd.addCoprocessorWithSpec("file:///some/path" + "|" + cpName); 086 fail(); 087 } catch (IllegalArgumentException iae) { 088 // Expected to be invalid 089 } 090 091 // Try more spec. 092 String spec = "hdfs:///foo.jar|com.foo.FooRegionObserver|1001|arg1=1,arg2=2"; 093 try { 094 htd.addCoprocessorWithSpec(spec); 095 } catch (IllegalArgumentException iae) { 096 fail(); 097 } 098 099 // Try double add of same coprocessor 100 try { 101 htd.addCoprocessorWithSpec(spec); 102 fail(); 103 } catch (IOException ioe) { 104 // Expect that the coprocessor already exists 105 } 106 } 107 108 @Test 109 public void testPb() throws DeserializationException, IOException { 110 HTableDescriptor htd = new HTableDescriptor(TableName.META_TABLE_NAME); 111 final int v = 123; 112 htd.setMaxFileSize(v); 113 htd.setDurability(Durability.ASYNC_WAL); 114 htd.setReadOnly(true); 115 htd.setRegionReplication(2); 116 byte [] bytes = htd.toByteArray(); 117 HTableDescriptor deserializedHtd = HTableDescriptor.parseFrom(bytes); 118 assertEquals(htd, deserializedHtd); 119 assertEquals(v, deserializedHtd.getMaxFileSize()); 120 assertTrue(deserializedHtd.isReadOnly()); 121 assertEquals(Durability.ASYNC_WAL, deserializedHtd.getDurability()); 122 assertEquals(2, deserializedHtd.getRegionReplication()); 123 } 124 125 /** 126 * Test cps in the table description. 127 * 128 * @throws Exception if adding a coprocessor fails 129 */ 130 @Test 131 public void testGetSetRemoveCP() throws Exception { 132 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName())); 133 // simple CP 134 String className = "org.apache.hadoop.hbase.coprocessor.SimpleRegionObserver"; 135 // add and check that it is present 136 desc.addCoprocessor(className); 137 assertTrue(desc.hasCoprocessor(className)); 138 // remove it and check that it is gone 139 desc.removeCoprocessor(className); 140 assertFalse(desc.hasCoprocessor(className)); 141 } 142 143 /** 144 * Test cps in the table description. 145 * 146 * @throws Exception if adding a coprocessor fails 147 */ 148 @Test 149 public void testSetListRemoveCP() throws Exception { 150 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName())); 151 // simple CP 152 String className1 = "org.apache.hadoop.hbase.coprocessor.SimpleRegionObserver"; 153 String className2 = "org.apache.hadoop.hbase.coprocessor.SampleRegionWALObserver"; 154 // Check that any coprocessor is present. 155 assertTrue(desc.getCoprocessors().isEmpty()); 156 157 // Add the 1 coprocessor and check if present. 158 desc.addCoprocessor(className1); 159 assertTrue(desc.getCoprocessors().size() == 1); 160 assertTrue(desc.getCoprocessors().contains(className1)); 161 162 // Add the 2nd coprocessor and check if present. 163 // remove it and check that it is gone 164 desc.addCoprocessor(className2); 165 assertTrue(desc.getCoprocessors().size() == 2); 166 assertTrue(desc.getCoprocessors().contains(className2)); 167 168 // Remove one and check 169 desc.removeCoprocessor(className1); 170 assertTrue(desc.getCoprocessors().size() == 1); 171 assertFalse(desc.getCoprocessors().contains(className1)); 172 assertTrue(desc.getCoprocessors().contains(className2)); 173 174 // Remove the last and check 175 desc.removeCoprocessor(className2); 176 assertTrue(desc.getCoprocessors().isEmpty()); 177 assertFalse(desc.getCoprocessors().contains(className1)); 178 assertFalse(desc.getCoprocessors().contains(className2)); 179 } 180 181 /** 182 * Test that we add and remove strings from settings properly. 183 */ 184 @Test 185 public void testAddGetRemoveString() { 186 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName())); 187 String key = "Some"; 188 String value = "value"; 189 desc.setValue(key, value); 190 assertEquals(value, desc.getValue(key)); 191 desc.remove(key); 192 assertEquals(null, desc.getValue(key)); 193 String keyShouldNotNull = "Some2"; 194 String valueIsNull = null; 195 desc.setValue(keyShouldNotNull, valueIsNull); 196 assertEquals(valueIsNull, desc.getValue(keyShouldNotNull)); 197 desc.remove(keyShouldNotNull); 198 assertEquals(null, desc.getValue(keyShouldNotNull)); 199 } 200 201 String[] legalTableNames = { "foo", "with-dash_under.dot", "_under_start_ok", 202 "with-dash.with_underscore", "02-01-2012.my_table_01-02", "xyz._mytable_", "9_9_0.table_02", 203 "dot1.dot2.table", "new.-mytable", "with-dash.with.dot", "legal..t2", "legal..legal.t2", 204 "trailingdots..", "trailing.dots...", "ns:mytable", "ns:_mytable_", "ns:my_table_01-02", 205 "汉", "汉:字", "_字_", "foo:字", "foo.字", "字.foo"}; 206 // Avoiding "zookeeper" in here as it's tough to encode in regex 207 String[] illegalTableNames = { ".dot_start_illegal", "-dash_start_illegal", "spaces not ok", 208 "-dash-.start_illegal", "new.table with space", "01 .table", "ns:-illegaldash", 209 "new:.illegaldot", "new:illegalcolon1:", "new:illegalcolon1:2", String.valueOf((char)130), 210 String.valueOf((char)5), String.valueOf((char)65530)}; 211 212 @Test 213 public void testLegalHTableNames() { 214 for (String tn : legalTableNames) { 215 TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn)); 216 } 217 } 218 219 @Test 220 public void testIllegalHTableNames() { 221 for (String tn : illegalTableNames) { 222 try { 223 TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn)); 224 fail("invalid tablename " + tn + " should have failed"); 225 } catch (Exception e) { 226 // expected 227 } 228 } 229 } 230 231 @Test 232 public void testIllegalZooKeeperName() { 233 for (String name : Arrays.asList("zookeeper", "ns:zookeeper", "zookeeper:table")) { 234 try { 235 TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(name)); 236 fail("invalid tablename " + name + " should have failed"); 237 } catch (Exception e) { 238 // expected 239 } 240 } 241 } 242 243 @Test 244 public void testLegalHTableNamesRegex() { 245 for (String tn : legalTableNames) { 246 TableName tName = TableName.valueOf(tn); 247 assertTrue("Testing: '" + tn + "'", Pattern.matches(TableName.VALID_USER_TABLE_REGEX, 248 tName.getNameAsString())); 249 } 250 } 251 252 @Test 253 public void testIllegalHTableNamesRegex() { 254 for (String tn : illegalTableNames) { 255 LOG.info("Testing: '" + tn + "'"); 256 assertFalse(Pattern.matches(TableName.VALID_USER_TABLE_REGEX, tn)); 257 } 258 } 259 260 /** 261 * Test default value handling for maxFileSize 262 */ 263 @Test 264 public void testGetMaxFileSize() { 265 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName())); 266 assertEquals(-1, desc.getMaxFileSize()); 267 desc.setMaxFileSize(1111L); 268 assertEquals(1111L, desc.getMaxFileSize()); 269 } 270 271 /** 272 * Test default value handling for memStoreFlushSize 273 */ 274 @Test 275 public void testGetMemStoreFlushSize() { 276 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName())); 277 assertEquals(-1, desc.getMemStoreFlushSize()); 278 desc.setMemStoreFlushSize(1111L); 279 assertEquals(1111L, desc.getMemStoreFlushSize()); 280 } 281 282 /** 283 * Test that we add and remove strings from configuration properly. 284 */ 285 @Test 286 public void testAddGetRemoveConfiguration() throws Exception { 287 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName())); 288 String key = "Some"; 289 String value = "value"; 290 desc.setConfiguration(key, value); 291 assertEquals(value, desc.getConfigurationValue(key)); 292 desc.removeConfiguration(key); 293 assertEquals(null, desc.getConfigurationValue(key)); 294 } 295 296 @Test 297 public void testClassMethodsAreBuilderStyle() { 298 /* HTableDescriptor should have a builder style setup where setXXX/addXXX methods 299 * can be chainable together: 300 * . For example: 301 * HTableDescriptor htd 302 * = new HTableDescriptor() 303 * .setFoo(foo) 304 * .setBar(bar) 305 * .setBuz(buz) 306 * 307 * This test ensures that all methods starting with "set" returns the declaring object 308 */ 309 310 BuilderStyleTest.assertClassesAreBuilderStyle(HTableDescriptor.class); 311 } 312 313 @Test 314 public void testModifyFamily() { 315 TableDescriptorBuilder.ModifyableTableDescriptor tableDescriptor = 316 new TableDescriptorBuilder.ModifyableTableDescriptor( 317 TableName.valueOf(name.getMethodName())); 318 byte[] familyName = Bytes.toBytes("cf"); 319 ColumnFamilyDescriptorBuilder.ModifyableColumnFamilyDescriptor familyDescriptor = 320 new ColumnFamilyDescriptorBuilder.ModifyableColumnFamilyDescriptor(familyName) 321 .setBlocksize(1000) 322 .setDFSReplication((short) 3); 323 tableDescriptor.setColumnFamily(familyDescriptor); 324 assertEquals(1000, tableDescriptor.getColumnFamily(familyName).getBlocksize()); 325 assertEquals(3, tableDescriptor.getColumnFamily(familyName).getDFSReplication()); 326 familyDescriptor = 327 new ColumnFamilyDescriptorBuilder.ModifyableColumnFamilyDescriptor(familyName) 328 .setBlocksize(2000) 329 .setDFSReplication((short) 1); 330 tableDescriptor.modifyColumnFamily(familyDescriptor); 331 assertEquals(2000, tableDescriptor.getColumnFamily(familyName).getBlocksize()); 332 assertEquals(1, tableDescriptor.getColumnFamily(familyName).getDFSReplication()); 333 } 334 335 @Test(expected=IllegalArgumentException.class) 336 public void testModifyInexistentFamily() { 337 TableDescriptorBuilder.ModifyableTableDescriptor tableDescriptor = 338 new TableDescriptorBuilder.ModifyableTableDescriptor( 339 TableName.valueOf(name.getMethodName())); 340 byte[] familyName = Bytes.toBytes("cf"); 341 ColumnFamilyDescriptorBuilder.ModifyableColumnFamilyDescriptor familyDescriptor = 342 new ColumnFamilyDescriptorBuilder.ModifyableColumnFamilyDescriptor(familyName); 343 tableDescriptor.modifyColumnFamily(familyDescriptor); 344 } 345 346 @Test(expected=IllegalArgumentException.class) 347 public void testAddDuplicateFamilies() { 348 TableDescriptorBuilder.ModifyableTableDescriptor tableDescriptor = 349 new TableDescriptorBuilder.ModifyableTableDescriptor( 350 TableName.valueOf(name.getMethodName())); 351 byte[] familyName = Bytes.toBytes("cf"); 352 ColumnFamilyDescriptorBuilder.ModifyableColumnFamilyDescriptor familyDescriptor = 353 new ColumnFamilyDescriptorBuilder.ModifyableColumnFamilyDescriptor(familyName) 354 .setBlocksize(1000); 355 tableDescriptor.setColumnFamily(familyDescriptor); 356 assertEquals(1000, tableDescriptor.getColumnFamily(familyName).getBlocksize()); 357 familyDescriptor = 358 new ColumnFamilyDescriptorBuilder.ModifyableColumnFamilyDescriptor(familyName) 359 .setBlocksize(2000); 360 tableDescriptor.setColumnFamily(familyDescriptor); 361 } 362 363 @Test 364 public void testPriority() { 365 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(name.getMethodName())); 366 htd.setPriority(42); 367 assertEquals(42, htd.getPriority()); 368 } 369}