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.apache.hadoop.hbase.client.AsyncProcess.START_LOG_ERRORS_AFTER_COUNT_KEY; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.assertNotNull; 023import static org.junit.Assert.assertNull; 024import static org.junit.Assert.assertTrue; 025import static org.junit.Assert.fail; 026 027import java.util.concurrent.Callable; 028import org.apache.hadoop.hbase.HBaseClassTestRule; 029import org.apache.hadoop.hbase.HColumnDescriptor; 030import org.apache.hadoop.hbase.HConstants; 031import org.apache.hadoop.hbase.HTableDescriptor; 032import org.apache.hadoop.hbase.NamespaceDescriptor; 033import org.apache.hadoop.hbase.NamespaceExistException; 034import org.apache.hadoop.hbase.NamespaceNotFoundException; 035import org.apache.hadoop.hbase.TableName; 036import org.apache.hadoop.hbase.Waiter; 037import org.apache.hadoop.hbase.ZKNamespaceManager; 038import org.apache.hadoop.hbase.master.HMaster; 039import org.apache.hadoop.hbase.testclassification.ClientTests; 040import org.apache.hadoop.hbase.testclassification.LargeTests; 041import org.junit.BeforeClass; 042import org.junit.ClassRule; 043import org.junit.Test; 044import org.junit.experimental.categories.Category; 045import org.junit.runner.RunWith; 046import org.junit.runners.Parameterized; 047 048/** 049 * Class to test asynchronous namespace admin operations. 050 */ 051@RunWith(Parameterized.class) 052@Category({ LargeTests.class, ClientTests.class }) 053public class TestAsyncNamespaceAdminApi extends TestAsyncAdminBase { 054 055 @ClassRule 056 public static final HBaseClassTestRule CLASS_RULE = 057 HBaseClassTestRule.forClass(TestAsyncNamespaceAdminApi.class); 058 059 private String prefix = "TestNamespace"; 060 private static HMaster master; 061 private static ZKNamespaceManager zkNamespaceManager; 062 063 @BeforeClass 064 public static void setUpBeforeClass() throws Exception { 065 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 60000); 066 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_OPERATION_TIMEOUT, 120000); 067 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 2); 068 TEST_UTIL.getConfiguration().setInt(START_LOG_ERRORS_AFTER_COUNT_KEY, 0); 069 TEST_UTIL.startMiniCluster(1); 070 ASYNC_CONN = ConnectionFactory.createAsyncConnection(TEST_UTIL.getConfiguration()).get(); 071 master = TEST_UTIL.getHBaseCluster().getMaster(); 072 zkNamespaceManager = new ZKNamespaceManager(master.getZooKeeper()); 073 zkNamespaceManager.start(); 074 LOG.info("Done initializing cluster"); 075 } 076 077 @Test 078 public void testCreateAndDelete() throws Exception { 079 String testName = "testCreateAndDelete"; 080 String nsName = prefix + "_" + testName; 081 082 // create namespace and verify 083 admin.createNamespace(NamespaceDescriptor.create(nsName).build()).join(); 084 assertEquals(3, admin.listNamespaceDescriptors().get().size()); 085 TEST_UTIL.waitFor(60000, new Waiter.Predicate<Exception>() { 086 @Override 087 public boolean evaluate() throws Exception { 088 return zkNamespaceManager.list().size() == 3; 089 } 090 }); 091 assertNotNull(zkNamespaceManager.get(nsName)); 092 // delete namespace and verify 093 admin.deleteNamespace(nsName).join(); 094 assertEquals(2, admin.listNamespaceDescriptors().get().size()); 095 assertEquals(2, zkNamespaceManager.list().size()); 096 assertNull(zkNamespaceManager.get(nsName)); 097 } 098 099 @Test 100 public void testDeleteReservedNS() throws Exception { 101 boolean exceptionCaught = false; 102 try { 103 admin.deleteNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR).join(); 104 } catch (Exception exp) { 105 LOG.warn(exp.toString(), exp); 106 exceptionCaught = true; 107 } finally { 108 assertTrue(exceptionCaught); 109 } 110 111 try { 112 admin.deleteNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR).join(); 113 } catch (Exception exp) { 114 LOG.warn(exp.toString(), exp); 115 exceptionCaught = true; 116 } finally { 117 assertTrue(exceptionCaught); 118 } 119 } 120 121 @Test 122 public void testNamespaceOperations() throws Exception { 123 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()).join(); 124 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns2").build()).join(); 125 126 // create namespace that already exists 127 runWithExpectedException(new Callable<Void>() { 128 @Override 129 public Void call() throws Exception { 130 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()).join(); 131 return null; 132 } 133 }, NamespaceExistException.class); 134 135 // create a table in non-existing namespace 136 runWithExpectedException(new Callable<Void>() { 137 @Override 138 public Void call() throws Exception { 139 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("non_existing_namespace", 140 "table1")); 141 htd.addFamily(new HColumnDescriptor("family1")); 142 admin.createTable(htd).join(); 143 return null; 144 } 145 }, NamespaceNotFoundException.class); 146 147 // get descriptor for existing namespace 148 NamespaceDescriptor ns1 = admin.getNamespaceDescriptor(prefix + "ns1").get(); 149 assertEquals(prefix + "ns1", ns1.getName()); 150 151 // get descriptor for non-existing namespace 152 runWithExpectedException(new Callable<NamespaceDescriptor>() { 153 @Override 154 public NamespaceDescriptor call() throws Exception { 155 return admin.getNamespaceDescriptor("non_existing_namespace").get(); 156 } 157 }, NamespaceNotFoundException.class); 158 159 // delete descriptor for existing namespace 160 admin.deleteNamespace(prefix + "ns2").join(); 161 162 // delete descriptor for non-existing namespace 163 runWithExpectedException(new Callable<Void>() { 164 @Override 165 public Void call() throws Exception { 166 admin.deleteNamespace("non_existing_namespace").join(); 167 return null; 168 } 169 }, NamespaceNotFoundException.class); 170 171 // modify namespace descriptor for existing namespace 172 ns1 = admin.getNamespaceDescriptor(prefix + "ns1").get(); 173 ns1.setConfiguration("foo", "bar"); 174 admin.modifyNamespace(ns1).join(); 175 ns1 = admin.getNamespaceDescriptor(prefix + "ns1").get(); 176 assertEquals("bar", ns1.getConfigurationValue("foo")); 177 178 // modify namespace descriptor for non-existing namespace 179 runWithExpectedException(new Callable<Void>() { 180 @Override 181 public Void call() throws Exception { 182 admin.modifyNamespace(NamespaceDescriptor.create("non_existing_namespace").build()).join(); 183 return null; 184 } 185 }, NamespaceNotFoundException.class); 186 187 admin.deleteNamespace(prefix + "ns1").join(); 188 } 189 190 private static <V, E> void runWithExpectedException(Callable<V> callable, Class<E> exceptionClass) { 191 try { 192 callable.call(); 193 } catch (Exception ex) { 194 LOG.info("Get exception is " + ex); 195 assertEquals(exceptionClass, ex.getCause().getClass()); 196 return; 197 } 198 fail("Should have thrown exception " + exceptionClass); 199 } 200}