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.client; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertFalse; 022import static org.junit.Assert.assertNull; 023import static org.junit.Assert.assertTrue; 024import static org.junit.Assert.fail; 025 026import java.io.IOException; 027import java.util.regex.Pattern; 028import org.apache.hadoop.hbase.HBaseClassTestRule; 029import org.apache.hadoop.hbase.TableName; 030import org.apache.hadoop.hbase.exceptions.DeserializationException; 031import org.apache.hadoop.hbase.exceptions.HBaseException; 032import org.apache.hadoop.hbase.rsgroup.RSGroupInfo; 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@Category({ MiscTests.class, SmallTests.class }) 049public class TestTableDescriptorBuilder { 050 @ClassRule 051 public static final HBaseClassTestRule CLASS_RULE = 052 HBaseClassTestRule.forClass(TestTableDescriptorBuilder.class); 053 054 private static final Logger LOG = LoggerFactory.getLogger(TestTableDescriptorBuilder.class); 055 056 @Rule 057 public TestName name = new TestName(); 058 059 @Test(expected = IOException.class) 060 public void testAddCoprocessorTwice() throws IOException { 061 String cpName = "a.b.c.d"; 062 TableDescriptorBuilder.newBuilder(TableName.META_TABLE_NAME).setCoprocessor(cpName) 063 .setCoprocessor(cpName).build(); 064 } 065 066 @Test 067 public void testPb() throws DeserializationException, IOException { 068 final int v = 123; 069 TableDescriptor htd = 070 TableDescriptorBuilder.newBuilder(TableName.META_TABLE_NAME).setMaxFileSize(v) 071 .setDurability(Durability.ASYNC_WAL).setReadOnly(true).setRegionReplication(2).build(); 072 073 byte[] bytes = TableDescriptorBuilder.toByteArray(htd); 074 TableDescriptor deserializedHtd = TableDescriptorBuilder.parseFrom(bytes); 075 assertEquals(htd, deserializedHtd); 076 assertEquals(v, deserializedHtd.getMaxFileSize()); 077 assertTrue(deserializedHtd.isReadOnly()); 078 assertEquals(Durability.ASYNC_WAL, deserializedHtd.getDurability()); 079 assertEquals(2, deserializedHtd.getRegionReplication()); 080 } 081 082 /** 083 * Test cps in the table description. 084 * @throws Exception if setting a coprocessor fails 085 */ 086 @Test 087 public void testGetSetRemoveCP() throws Exception { 088 // simple CP 089 String className = "org.apache.hadoop.hbase.coprocessor.SimpleRegionObserver"; 090 TableDescriptor desc = TableDescriptorBuilder 091 .newBuilder(TableName.valueOf(name.getMethodName())).setCoprocessor(className) // add and 092 // check that 093 // it is 094 // present 095 .build(); 096 assertTrue(desc.hasCoprocessor(className)); 097 desc = TableDescriptorBuilder.newBuilder(desc).removeCoprocessor(className) // remove it and 098 // check that it is 099 // gone 100 .build(); 101 assertFalse(desc.hasCoprocessor(className)); 102 } 103 104 /** 105 * Test cps in the table description. 106 * @throws Exception if setting a coprocessor fails 107 */ 108 @Test 109 public void testSetListRemoveCP() throws Exception { 110 TableDescriptor desc = 111 TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())).build(); 112 // Check that any coprocessor is present. 113 assertTrue(desc.getCoprocessorDescriptors().isEmpty()); 114 115 // simple CP 116 String className1 = "org.apache.hadoop.hbase.coprocessor.SimpleRegionObserver"; 117 String className2 = "org.apache.hadoop.hbase.coprocessor.SampleRegionWALObserver"; 118 // Add the 1 coprocessor and check if present. 119 desc = TableDescriptorBuilder.newBuilder(desc).setCoprocessor(className1).build(); 120 assertTrue(desc.getCoprocessorDescriptors().size() == 1); 121 assertTrue(desc.getCoprocessorDescriptors().stream().map(CoprocessorDescriptor::getClassName) 122 .anyMatch(name -> name.equals(className1))); 123 // Add the 2nd coprocessor and check if present. 124 // remove it and check that it is gone 125 desc = TableDescriptorBuilder.newBuilder(desc) 126 127 .setCoprocessor(className2).build(); 128 assertTrue(desc.getCoprocessorDescriptors().size() == 2); 129 assertTrue(desc.getCoprocessorDescriptors().stream().map(CoprocessorDescriptor::getClassName) 130 .anyMatch(name -> name.equals(className2))); 131 // Remove one and check 132 desc = TableDescriptorBuilder.newBuilder(desc) 133 134 .removeCoprocessor(className1).build(); 135 assertTrue(desc.getCoprocessorDescriptors().size() == 1); 136 assertFalse(desc.getCoprocessorDescriptors().stream().map(CoprocessorDescriptor::getClassName) 137 .anyMatch(name -> name.equals(className1))); 138 assertTrue(desc.getCoprocessorDescriptors().stream().map(CoprocessorDescriptor::getClassName) 139 .anyMatch(name -> name.equals(className2))); 140 // Remove the last and check 141 desc = TableDescriptorBuilder.newBuilder(desc) 142 143 .removeCoprocessor(className2).build(); 144 assertTrue(desc.getCoprocessorDescriptors().isEmpty()); 145 assertFalse(desc.getCoprocessorDescriptors().stream().map(CoprocessorDescriptor::getClassName) 146 .anyMatch(name -> name.equals(className1))); 147 assertFalse(desc.getCoprocessorDescriptors().stream().map(CoprocessorDescriptor::getClassName) 148 .anyMatch(name -> name.equals(className2))); 149 } 150 151 /** 152 * Test removing cps in the table description that does not exist 153 * @throws Exception if removing a coprocessor fails other than IllegalArgumentException 154 */ 155 @Test(expected = IllegalArgumentException.class) 156 public void testRemoveNonExistingCoprocessor() throws Exception { 157 String className = "org.apache.hadoop.hbase.coprocessor.SimpleRegionObserver"; 158 TableDescriptor desc = 159 TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())).build(); 160 assertFalse(desc.hasCoprocessor(className)); 161 TableDescriptorBuilder.newBuilder(desc).removeCoprocessor(className).build(); 162 } 163 164 /** 165 * Test that we add and remove strings from settings properly. 166 */ 167 @Test 168 public void testRemoveString() { 169 byte[] key = Bytes.toBytes("Some"); 170 byte[] value = Bytes.toBytes("value"); 171 TableDescriptor desc = TableDescriptorBuilder 172 .newBuilder(TableName.valueOf(name.getMethodName())).setValue(key, value).build(); 173 assertTrue(Bytes.equals(value, desc.getValue(key))); 174 desc = TableDescriptorBuilder.newBuilder(desc).removeValue(key).build(); 175 assertTrue(desc.getValue(key) == null); 176 } 177 178 String[] legalTableNames = { "foo", "with-dash_under.dot", "_under_start_ok", 179 "with-dash.with_underscore", "02-01-2012.my_table_01-02", "xyz._mytable_", "9_9_0.table_02", 180 "dot1.dot2.table", "new.-mytable", "with-dash.with.dot", "legal..t2", "legal..legal.t2", 181 "trailingdots..", "trailing.dots...", "ns:mytable", "ns:_mytable_", "ns:my_table_01-02" }; 182 String[] illegalTableNames = { ".dot_start_illegal", "-dash_start_illegal", "spaces not ok", 183 "-dash-.start_illegal", "new.table with space", "01 .table", "ns:-illegaldash", 184 "new:.illegaldot", "new:illegalcolon1:", "new:illegalcolon1:2" }; 185 186 @Test 187 public void testLegalTableNames() { 188 for (String tn : legalTableNames) { 189 TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn)); 190 } 191 } 192 193 @Test 194 public void testIllegalTableNames() { 195 for (String tn : illegalTableNames) { 196 try { 197 TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn)); 198 fail("invalid tablename " + tn + " should have failed"); 199 } catch (Exception e) { 200 // expected 201 } 202 } 203 } 204 205 @Test 206 public void testLegalTableNamesRegex() { 207 for (String tn : legalTableNames) { 208 TableName tName = TableName.valueOf(tn); 209 assertTrue("Testing: '" + tn + "'", 210 Pattern.matches(TableName.VALID_USER_TABLE_REGEX, tName.getNameAsString())); 211 } 212 } 213 214 @Test 215 public void testIllegalTableNamesRegex() { 216 for (String tn : illegalTableNames) { 217 LOG.info("Testing: '" + tn + "'"); 218 assertFalse(Pattern.matches(TableName.VALID_USER_TABLE_REGEX, tn)); 219 } 220 } 221 222 /** 223 * Test default value handling for maxFileSize 224 */ 225 @Test 226 public void testGetMaxFileSize() { 227 TableDescriptor desc = 228 TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())).build(); 229 assertEquals(-1, desc.getMaxFileSize()); 230 desc = TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())) 231 .setMaxFileSize(1111L).build(); 232 assertEquals(1111L, desc.getMaxFileSize()); 233 } 234 235 @Test 236 public void testSetMaxFileSize() throws HBaseException { 237 TableDescriptorBuilder builder = 238 TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())); 239 240 String maxFileSize = "1073741824"; 241 builder.setMaxFileSize(maxFileSize); 242 assertEquals(1073741824, builder.build().getMaxFileSize()); 243 244 maxFileSize = "1GB"; 245 builder.setMaxFileSize(maxFileSize); 246 assertEquals(1073741824, builder.build().getMaxFileSize()); 247 248 maxFileSize = "10GB 25MB"; 249 builder.setMaxFileSize(maxFileSize); 250 assertEquals(10763632640L, builder.build().getMaxFileSize()); 251 252 // ignore case 253 maxFileSize = "10GB 512mb 512KB 512b"; 254 builder.setMaxFileSize(maxFileSize); 255 assertEquals(11274813952L, builder.build().getMaxFileSize()); 256 257 maxFileSize = "10737942528 B (10GB 512KB)"; 258 builder.setMaxFileSize(maxFileSize); 259 assertEquals(10737942528L, builder.build().getMaxFileSize()); 260 } 261 262 /** 263 * Test default value handling for memStoreFlushSize 264 */ 265 @Test 266 public void testGetMemStoreFlushSize() { 267 TableDescriptor desc = 268 TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())).build(); 269 assertEquals(-1, desc.getMemStoreFlushSize()); 270 desc = TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())) 271 .setMemStoreFlushSize(1111L).build(); 272 assertEquals(1111L, desc.getMemStoreFlushSize()); 273 } 274 275 @Test 276 public void testSetMemStoreFlushSize() throws HBaseException { 277 TableDescriptorBuilder builder = 278 TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())); 279 280 String memstoreFlushSize = "1073741824"; 281 builder.setMemStoreFlushSize(memstoreFlushSize); 282 assertEquals(1073741824, builder.build().getMemStoreFlushSize()); 283 284 memstoreFlushSize = "1GB"; 285 builder.setMemStoreFlushSize(memstoreFlushSize); 286 assertEquals(1073741824, builder.build().getMemStoreFlushSize()); 287 288 memstoreFlushSize = "10GB 25MB"; 289 builder.setMemStoreFlushSize(memstoreFlushSize); 290 assertEquals(10763632640L, builder.build().getMemStoreFlushSize()); 291 292 // ignore case 293 memstoreFlushSize = "10GB 512mb 512KB 512b"; 294 builder.setMemStoreFlushSize(memstoreFlushSize); 295 assertEquals(11274813952L, builder.build().getMemStoreFlushSize()); 296 297 memstoreFlushSize = "10737942528 B (10GB 512KB)"; 298 builder.setMemStoreFlushSize(memstoreFlushSize); 299 assertEquals(10737942528L, builder.build().getMemStoreFlushSize()); 300 } 301 302 @Test 303 public void testClassMethodsAreBuilderStyle() { 304 BuilderStyleTest.assertClassesAreBuilderStyle(TableDescriptorBuilder.class); 305 } 306 307 @Test 308 public void testModifyFamily() { 309 byte[] familyName = Bytes.toBytes("cf"); 310 ColumnFamilyDescriptor hcd = ColumnFamilyDescriptorBuilder.newBuilder(familyName) 311 .setBlocksize(1000).setDFSReplication((short) 3).build(); 312 TableDescriptor htd = TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())) 313 .setColumnFamily(hcd).build(); 314 315 assertEquals(1000, htd.getColumnFamily(familyName).getBlocksize()); 316 assertEquals(3, htd.getColumnFamily(familyName).getDFSReplication()); 317 hcd = ColumnFamilyDescriptorBuilder.newBuilder(familyName).setBlocksize(2000) 318 .setDFSReplication((short) 1).build(); 319 htd = TableDescriptorBuilder.newBuilder(htd).modifyColumnFamily(hcd).build(); 320 assertEquals(2000, htd.getColumnFamily(familyName).getBlocksize()); 321 assertEquals(1, htd.getColumnFamily(familyName).getDFSReplication()); 322 } 323 324 @Test(expected = IllegalArgumentException.class) 325 public void testModifyInexistentFamily() { 326 byte[] familyName = Bytes.toBytes("cf"); 327 TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())) 328 .modifyColumnFamily(ColumnFamilyDescriptorBuilder.of(familyName)).build(); 329 } 330 331 @Test(expected = IllegalArgumentException.class) 332 public void testAddDuplicateFamilies() { 333 byte[] familyName = Bytes.toBytes("cf"); 334 ColumnFamilyDescriptor hcd = 335 ColumnFamilyDescriptorBuilder.newBuilder(familyName).setBlocksize(1000).build(); 336 TableDescriptor htd = TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())) 337 .setColumnFamily(hcd).build(); 338 assertEquals(1000, htd.getColumnFamily(familyName).getBlocksize()); 339 hcd = ColumnFamilyDescriptorBuilder.newBuilder(familyName).setBlocksize(2000).build(); 340 // add duplicate column 341 TableDescriptorBuilder.newBuilder(htd).setColumnFamily(hcd).build(); 342 } 343 344 @Test 345 public void testPriority() { 346 TableDescriptor htd = TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())) 347 .setPriority(42).build(); 348 assertEquals(42, htd.getPriority()); 349 } 350 351 @Test 352 public void testStringCustomizedValues() throws HBaseException { 353 byte[] familyName = Bytes.toBytes("cf"); 354 ColumnFamilyDescriptor hcd = 355 ColumnFamilyDescriptorBuilder.newBuilder(familyName).setBlocksize(131072).build(); 356 TableDescriptor htd = TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())) 357 .setColumnFamily(hcd).setDurability(Durability.ASYNC_WAL).build(); 358 359 assertEquals( 360 "'testStringCustomizedValues', " + "{TABLE_ATTRIBUTES => {DURABILITY => 'ASYNC_WAL'}}, " 361 + "{NAME => 'cf', BLOCKSIZE => '131072 B (128KB)'}", 362 htd.toStringCustomizedValues()); 363 364 htd = TableDescriptorBuilder.newBuilder(htd).setMaxFileSize("10737942528") 365 .setMemStoreFlushSize("256MB").setErasureCodingPolicy("RS-6-3-1024k").build(); 366 assertEquals( 367 "'testStringCustomizedValues', " + "{TABLE_ATTRIBUTES => {DURABILITY => 'ASYNC_WAL', " 368 + "ERASURE_CODING_POLICY => 'RS-6-3-1024k', MAX_FILESIZE => '10737942528 B (10GB 512KB)', " 369 + "MEMSTORE_FLUSHSIZE => '268435456 B (256MB)'}}, " 370 + "{NAME => 'cf', BLOCKSIZE => '131072 B (128KB)'}", 371 htd.toStringCustomizedValues()); 372 } 373 374 @Test 375 public void testGetSetRegionServerGroup() { 376 String groupName = name.getMethodName(); 377 TableDescriptor htd = TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())) 378 .setRegionServerGroup(groupName).build(); 379 assertEquals(htd.getValue(RSGroupInfo.TABLE_DESC_PROP_GROUP), groupName); 380 htd = TableDescriptorBuilder.newBuilder(htd).setRegionServerGroup(null).build(); 381 assertNull(htd.getValue(RSGroupInfo.TABLE_DESC_PROP_GROUP)); 382 } 383 384 @Test 385 public void testSetEmptyValue() { 386 TableDescriptorBuilder builder = 387 TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName())); 388 String testValue = "TestValue"; 389 // test setValue 390 builder.setValue(testValue, "2"); 391 assertEquals("2", builder.build().getValue(testValue)); 392 builder.setValue(testValue, ""); 393 assertNull(builder.build().getValue(Bytes.toBytes(testValue))); 394 395 // test setFlushPolicyClassName 396 builder.setFlushPolicyClassName("class"); 397 assertEquals("class", builder.build().getFlushPolicyClassName()); 398 builder.setFlushPolicyClassName(""); 399 assertNull(builder.build().getFlushPolicyClassName()); 400 } 401}