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