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.jupiter.api.Assertions.assertEquals; 021import static org.junit.jupiter.api.Assertions.assertNotNull; 022import static org.junit.jupiter.api.Assertions.assertTrue; 023import static org.junit.jupiter.api.Assertions.fail; 024 025import java.io.IOException; 026import java.util.List; 027import java.util.Set; 028import java.util.concurrent.Callable; 029import java.util.regex.Pattern; 030import org.apache.hadoop.fs.FileSystem; 031import org.apache.hadoop.fs.Path; 032import org.apache.hadoop.hbase.client.Admin; 033import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; 034import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 035import org.apache.hadoop.hbase.client.Get; 036import org.apache.hadoop.hbase.client.Put; 037import org.apache.hadoop.hbase.client.Table; 038import org.apache.hadoop.hbase.client.TableDescriptor; 039import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 040import org.apache.hadoop.hbase.master.HMaster; 041import org.apache.hadoop.hbase.testclassification.MediumTests; 042import org.apache.hadoop.hbase.testclassification.MiscTests; 043import org.apache.hadoop.hbase.util.Bytes; 044import org.junit.jupiter.api.AfterAll; 045import org.junit.jupiter.api.BeforeAll; 046import org.junit.jupiter.api.BeforeEach; 047import org.junit.jupiter.api.Tag; 048import org.junit.jupiter.api.Test; 049import org.junit.jupiter.api.TestInfo; 050import org.slf4j.Logger; 051import org.slf4j.LoggerFactory; 052 053import org.apache.hbase.thirdparty.com.google.common.collect.Sets; 054 055@Tag(MiscTests.TAG) 056@Tag(MediumTests.TAG) 057public class TestNamespace { 058 059 private static final Logger LOG = LoggerFactory.getLogger(TestNamespace.class); 060 private static HMaster master; 061 protected final static int NUM_SLAVES_BASE = 4; 062 private static HBaseTestingUtil TEST_UTIL; 063 protected static Admin admin; 064 protected static HBaseClusterInterface cluster; 065 private String prefix = "TestNamespace"; 066 067 @BeforeAll 068 public static void setUp() throws Exception { 069 TEST_UTIL = new HBaseTestingUtil(); 070 TEST_UTIL.startMiniCluster(NUM_SLAVES_BASE); 071 admin = TEST_UTIL.getAdmin(); 072 cluster = TEST_UTIL.getHBaseCluster(); 073 master = ((SingleProcessHBaseCluster) cluster).getMaster(); 074 LOG.info("Done initializing cluster"); 075 } 076 077 @AfterAll 078 public static void tearDown() throws Exception { 079 TEST_UTIL.shutdownMiniCluster(); 080 } 081 082 @BeforeEach 083 public void beforeMethod() throws IOException { 084 for (TableDescriptor desc : admin.listTableDescriptors(Pattern.compile(prefix + ".*"))) { 085 admin.disableTable(desc.getTableName()); 086 admin.deleteTable(desc.getTableName()); 087 } 088 for (NamespaceDescriptor ns : admin.listNamespaceDescriptors()) { 089 if (ns.getName().startsWith(prefix)) { 090 admin.deleteNamespace(ns.getName()); 091 } 092 } 093 } 094 095 @Test 096 public void verifyReservedNS() throws IOException { 097 // verify existence of reserved namespaces 098 NamespaceDescriptor ns = 099 admin.getNamespaceDescriptor(NamespaceDescriptor.DEFAULT_NAMESPACE.getName()); 100 assertNotNull(ns); 101 assertEquals(ns.getName(), NamespaceDescriptor.DEFAULT_NAMESPACE.getName()); 102 103 ns = admin.getNamespaceDescriptor(NamespaceDescriptor.SYSTEM_NAMESPACE.getName()); 104 assertNotNull(ns); 105 assertEquals(ns.getName(), NamespaceDescriptor.SYSTEM_NAMESPACE.getName()); 106 107 assertEquals(2, admin.listNamespaces().length); 108 assertEquals(2, admin.listNamespaceDescriptors().length); 109 110 // verify existence of system tables 111 Set<TableName> systemTables = Sets.newHashSet(TableName.META_TABLE_NAME); 112 List<TableDescriptor> descs = admin.listTableDescriptorsByNamespace( 113 Bytes.toBytes(NamespaceDescriptor.SYSTEM_NAMESPACE.getName())); 114 assertEquals(systemTables.size(), descs.size()); 115 for (TableDescriptor desc : descs) { 116 assertTrue(systemTables.contains(desc.getTableName())); 117 } 118 // verify system tables aren't listed 119 assertEquals(0, admin.listTableDescriptors().size()); 120 121 // Try creating default and system namespaces. 122 boolean exceptionCaught = false; 123 try { 124 admin.createNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE); 125 } catch (IOException exp) { 126 LOG.warn(exp.toString(), exp); 127 exceptionCaught = true; 128 } finally { 129 assertTrue(exceptionCaught); 130 } 131 132 exceptionCaught = false; 133 try { 134 admin.createNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE); 135 } catch (IOException exp) { 136 LOG.warn(exp.toString(), exp); 137 exceptionCaught = true; 138 } finally { 139 assertTrue(exceptionCaught); 140 } 141 } 142 143 @Test 144 public void testDeleteReservedNS() throws Exception { 145 boolean exceptionCaught = false; 146 try { 147 admin.deleteNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR); 148 } catch (IOException exp) { 149 LOG.warn(exp.toString(), exp); 150 exceptionCaught = true; 151 } finally { 152 assertTrue(exceptionCaught); 153 } 154 155 try { 156 admin.deleteNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR); 157 } catch (IOException exp) { 158 LOG.warn(exp.toString(), exp); 159 exceptionCaught = true; 160 } finally { 161 assertTrue(exceptionCaught); 162 } 163 } 164 165 @Test 166 public void createRemoveTest(TestInfo testInfo) throws Exception { 167 String nsName = prefix + "_" + testInfo.getTestMethod().get().getName(); 168 LOG.info(testInfo.getTestMethod().get().getName()); 169 170 // create namespace and verify 171 admin.createNamespace(NamespaceDescriptor.create(nsName).build()); 172 assertEquals(3, admin.listNamespaces().length); 173 assertEquals(3, admin.listNamespaceDescriptors().length); 174 // remove namespace and verify 175 admin.deleteNamespace(nsName); 176 assertEquals(2, admin.listNamespaces().length); 177 assertEquals(2, admin.listNamespaceDescriptors().length); 178 } 179 180 @Test 181 public void createDoubleTest(TestInfo testInfo) throws IOException, InterruptedException { 182 String nsName = prefix + "_" + testInfo.getTestMethod().get().getName(); 183 LOG.info(testInfo.getTestMethod().get().getName()); 184 185 final TableName tableName = TableName.valueOf(testInfo.getTestMethod().get().getName()); 186 final TableName tableNameFoo = 187 TableName.valueOf(nsName + ":" + testInfo.getTestMethod().get().getName()); 188 // create namespace and verify 189 admin.createNamespace(NamespaceDescriptor.create(nsName).build()); 190 TEST_UTIL.createTable(tableName, Bytes.toBytes(nsName)); 191 TEST_UTIL.createTable(tableNameFoo, Bytes.toBytes(nsName)); 192 assertEquals(2, admin.listTableDescriptors().size()); 193 assertNotNull(admin.getDescriptor(tableName)); 194 assertNotNull(admin.getDescriptor(tableNameFoo)); 195 // remove namespace and verify 196 admin.disableTable(tableName); 197 admin.deleteTable(tableName); 198 assertEquals(1, admin.listTableDescriptors().size()); 199 } 200 201 @Test 202 public void createTableTest(TestInfo testInfo) throws IOException, InterruptedException { 203 String nsName = prefix + "_" + testInfo.getTestMethod().get().getName(); 204 LOG.info(testInfo.getTestMethod().get().getName()); 205 206 TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder 207 .newBuilder(TableName.valueOf(nsName + ":" + testInfo.getTestMethod().get().getName())); 208 ColumnFamilyDescriptor columnFamilyDescriptor = 209 ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("my_cf")).build(); 210 tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor); 211 TableDescriptor tableDescriptor = tableDescriptorBuilder.build(); 212 try { 213 admin.createTable(tableDescriptor); 214 fail("Expected no namespace exists exception"); 215 } catch (NamespaceNotFoundException ex) { 216 } 217 // create table and in new namespace 218 admin.createNamespace(NamespaceDescriptor.create(nsName).build()); 219 admin.createTable(tableDescriptor); 220 TEST_UTIL.waitTableAvailable(tableDescriptor.getTableName().getName(), 10000); 221 FileSystem fs = FileSystem.get(TEST_UTIL.getConfiguration()); 222 assertTrue(fs.exists( 223 new Path(master.getMasterFileSystem().getRootDir(), new Path(HConstants.BASE_NAMESPACE_DIR, 224 new Path(nsName, tableDescriptor.getTableName().getQualifierAsString()))))); 225 assertEquals(1, admin.listTableDescriptors().size()); 226 227 // verify non-empty namespace can't be removed 228 try { 229 admin.deleteNamespace(nsName); 230 fail("Expected non-empty namespace constraint exception"); 231 } catch (Exception ex) { 232 LOG.info("Caught expected exception: " + ex); 233 } 234 235 // sanity check try to write and read from table 236 Table table = TEST_UTIL.getConnection().getTable(tableDescriptor.getTableName()); 237 Put p = new Put(Bytes.toBytes("row1")); 238 p.addColumn(Bytes.toBytes("my_cf"), Bytes.toBytes("my_col"), Bytes.toBytes("value1")); 239 table.put(p); 240 // flush and read from disk to make sure directory changes are working 241 admin.flush(tableDescriptor.getTableName()); 242 Get g = new Get(Bytes.toBytes("row1")); 243 assertTrue(table.exists(g)); 244 245 // normal case of removing namespace 246 TEST_UTIL.deleteTable(tableDescriptor.getTableName()); 247 admin.deleteNamespace(nsName); 248 } 249 250 @Test 251 public void createTableInDefaultNamespace(TestInfo testInfo) throws Exception { 252 TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder 253 .newBuilder(TableName.valueOf(testInfo.getTestMethod().get().getName())); 254 ColumnFamilyDescriptor columnFamilyDescriptor = 255 ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("cf1")).build(); 256 tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor); 257 TableDescriptor tableDescriptor = tableDescriptorBuilder.build(); 258 admin.createTable(tableDescriptor); 259 assertTrue(admin.listTableDescriptors().size() == 1); 260 admin.disableTable(tableDescriptor.getTableName()); 261 admin.deleteTable(tableDescriptor.getTableName()); 262 } 263 264 @Test 265 public void createTableInSystemNamespace(TestInfo testInfo) throws Exception { 266 final TableName tableName = 267 TableName.valueOf("hbase:" + testInfo.getTestMethod().get().getName()); 268 TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(tableName); 269 ColumnFamilyDescriptor columnFamilyDescriptor = 270 ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("cf1")).build(); 271 tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor); 272 TableDescriptor tableDescriptor = tableDescriptorBuilder.build(); 273 admin.createTable(tableDescriptor); 274 assertEquals(0, admin.listTableDescriptors().size()); 275 assertTrue(admin.tableExists(tableName)); 276 admin.disableTable(tableDescriptor.getTableName()); 277 admin.deleteTable(tableDescriptor.getTableName()); 278 } 279 280 @Test 281 public void testNamespaceOperations(TestInfo testInfo) throws IOException { 282 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()); 283 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns2").build()); 284 285 // create namespace that already exists 286 runWithExpectedException(new Callable<Void>() { 287 @Override 288 public Void call() throws Exception { 289 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()); 290 return null; 291 } 292 }, NamespaceExistException.class); 293 294 // create a table in non-existing namespace 295 runWithExpectedException(new Callable<Void>() { 296 @Override 297 public Void call() throws Exception { 298 TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder( 299 TableName.valueOf("non_existing_namespace", testInfo.getTestMethod().get().getName())); 300 ColumnFamilyDescriptor columnFamilyDescriptor = 301 ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("family1")).build(); 302 tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor); 303 admin.createTable(tableDescriptorBuilder.build()); 304 return null; 305 } 306 }, NamespaceNotFoundException.class); 307 308 // get descriptor for existing namespace 309 admin.getNamespaceDescriptor(prefix + "ns1"); 310 311 // get descriptor for non-existing namespace 312 runWithExpectedException(new Callable<NamespaceDescriptor>() { 313 @Override 314 public NamespaceDescriptor call() throws Exception { 315 return admin.getNamespaceDescriptor("non_existing_namespace"); 316 } 317 }, NamespaceNotFoundException.class); 318 319 // delete descriptor for existing namespace 320 admin.deleteNamespace(prefix + "ns2"); 321 322 // delete descriptor for non-existing namespace 323 runWithExpectedException(new Callable<Void>() { 324 @Override 325 public Void call() throws Exception { 326 admin.deleteNamespace("non_existing_namespace"); 327 return null; 328 } 329 }, NamespaceNotFoundException.class); 330 331 // modify namespace descriptor for existing namespace 332 NamespaceDescriptor ns1 = admin.getNamespaceDescriptor(prefix + "ns1"); 333 ns1.setConfiguration("foo", "bar"); 334 admin.modifyNamespace(ns1); 335 336 // modify namespace descriptor for non-existing namespace 337 runWithExpectedException(new Callable<Void>() { 338 @Override 339 public Void call() throws Exception { 340 admin.modifyNamespace(NamespaceDescriptor.create("non_existing_namespace").build()); 341 return null; 342 } 343 }, NamespaceNotFoundException.class); 344 345 // get table descriptors for existing namespace 346 TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder 347 .newBuilder(TableName.valueOf(prefix + "ns1", testInfo.getTestMethod().get().getName())); 348 ColumnFamilyDescriptor columnFamilyDescriptor = 349 ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("family1")).build(); 350 tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor); 351 admin.createTable(tableDescriptorBuilder.build()); 352 List<TableDescriptor> htds = 353 admin.listTableDescriptorsByNamespace(Bytes.toBytes(prefix + "ns1")); 354 assertNotNull(htds, "Should have not returned null"); 355 assertEquals(1, htds.size(), "Should have returned non-empty array"); 356 357 // get table descriptors for non-existing namespace 358 runWithExpectedException(new Callable<Void>() { 359 @Override 360 public Void call() throws Exception { 361 admin.listTableDescriptorsByNamespace(Bytes.toBytes("non_existant_namespace")); 362 return null; 363 } 364 }, NamespaceNotFoundException.class); 365 366 // get table names for existing namespace 367 TableName[] tableNames = admin.listTableNamesByNamespace(prefix + "ns1"); 368 assertNotNull(tableNames, "Should have not returned null"); 369 assertEquals(1, tableNames.length, "Should have returned non-empty array"); 370 371 // get table names for non-existing namespace 372 runWithExpectedException(new Callable<Void>() { 373 @Override 374 public Void call() throws Exception { 375 admin.listTableNamesByNamespace("non_existing_namespace"); 376 return null; 377 } 378 }, NamespaceNotFoundException.class); 379 380 } 381 382 private static <V, E> void runWithExpectedException(Callable<V> callable, 383 Class<E> exceptionClass) { 384 try { 385 callable.call(); 386 } catch (Exception ex) { 387 assertEquals(exceptionClass, ex.getClass()); 388 return; 389 } 390 fail("Should have thrown exception " + exceptionClass); 391 } 392}