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.listNamespaces().get().size()); 085 assertEquals(3, admin.listNamespaceDescriptors().get().size()); 086 TEST_UTIL.waitFor(60000, new Waiter.Predicate<Exception>() { 087 @Override 088 public boolean evaluate() throws Exception { 089 return zkNamespaceManager.list().size() == 3; 090 } 091 }); 092 assertNotNull(zkNamespaceManager.get(nsName)); 093 // delete namespace and verify 094 admin.deleteNamespace(nsName).join(); 095 assertEquals(2, admin.listNamespaces().get().size()); 096 assertEquals(2, admin.listNamespaceDescriptors().get().size()); 097 assertEquals(2, zkNamespaceManager.list().size()); 098 assertNull(zkNamespaceManager.get(nsName)); 099 } 100 101 @Test 102 public void testDeleteReservedNS() throws Exception { 103 boolean exceptionCaught = false; 104 try { 105 admin.deleteNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR).join(); 106 } catch (Exception exp) { 107 LOG.warn(exp.toString(), exp); 108 exceptionCaught = true; 109 } finally { 110 assertTrue(exceptionCaught); 111 } 112 113 try { 114 admin.deleteNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR).join(); 115 } catch (Exception exp) { 116 LOG.warn(exp.toString(), exp); 117 exceptionCaught = true; 118 } finally { 119 assertTrue(exceptionCaught); 120 } 121 } 122 123 @Test 124 public void testNamespaceOperations() throws Exception { 125 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()).join(); 126 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns2").build()).join(); 127 128 // create namespace that already exists 129 runWithExpectedException(new Callable<Void>() { 130 @Override 131 public Void call() throws Exception { 132 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()).join(); 133 return null; 134 } 135 }, NamespaceExistException.class); 136 137 // create a table in non-existing namespace 138 runWithExpectedException(new Callable<Void>() { 139 @Override 140 public Void call() throws Exception { 141 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("non_existing_namespace", 142 "table1")); 143 htd.addFamily(new HColumnDescriptor("family1")); 144 admin.createTable(htd).join(); 145 return null; 146 } 147 }, NamespaceNotFoundException.class); 148 149 // get descriptor for existing namespace 150 NamespaceDescriptor ns1 = admin.getNamespaceDescriptor(prefix + "ns1").get(); 151 assertEquals(prefix + "ns1", ns1.getName()); 152 153 // get descriptor for non-existing namespace 154 runWithExpectedException(new Callable<NamespaceDescriptor>() { 155 @Override 156 public NamespaceDescriptor call() throws Exception { 157 return admin.getNamespaceDescriptor("non_existing_namespace").get(); 158 } 159 }, NamespaceNotFoundException.class); 160 161 // delete descriptor for existing namespace 162 admin.deleteNamespace(prefix + "ns2").join(); 163 164 // delete descriptor for non-existing namespace 165 runWithExpectedException(new Callable<Void>() { 166 @Override 167 public Void call() throws Exception { 168 admin.deleteNamespace("non_existing_namespace").join(); 169 return null; 170 } 171 }, NamespaceNotFoundException.class); 172 173 // modify namespace descriptor for existing namespace 174 ns1 = admin.getNamespaceDescriptor(prefix + "ns1").get(); 175 ns1.setConfiguration("foo", "bar"); 176 admin.modifyNamespace(ns1).join(); 177 ns1 = admin.getNamespaceDescriptor(prefix + "ns1").get(); 178 assertEquals("bar", ns1.getConfigurationValue("foo")); 179 180 // modify namespace descriptor for non-existing namespace 181 runWithExpectedException(new Callable<Void>() { 182 @Override 183 public Void call() throws Exception { 184 admin.modifyNamespace(NamespaceDescriptor.create("non_existing_namespace").build()).join(); 185 return null; 186 } 187 }, NamespaceNotFoundException.class); 188 189 admin.deleteNamespace(prefix + "ns1").join(); 190 } 191 192 private static <V, E> void runWithExpectedException(Callable<V> callable, Class<E> exceptionClass) { 193 try { 194 callable.call(); 195 } catch (Exception ex) { 196 LOG.info("Get exception is " + ex); 197 assertEquals(exceptionClass, ex.getCause().getClass()); 198 return; 199 } 200 fail("Should have thrown exception " + exceptionClass); 201 } 202}