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.TableName.META_TABLE_NAME;
021import static org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTrackerFactory.TRACKER_IMPL;
022import static org.junit.Assert.assertEquals;
023import static org.junit.Assert.assertFalse;
024import static org.junit.Assert.assertTrue;
025import static org.junit.Assert.fail;
026
027import java.util.ArrayList;
028import java.util.HashMap;
029import java.util.Iterator;
030import java.util.List;
031import java.util.Map;
032import java.util.Optional;
033import java.util.concurrent.CompletionException;
034import org.apache.hadoop.hbase.AsyncMetaTableAccessor;
035import org.apache.hadoop.hbase.HBaseClassTestRule;
036import org.apache.hadoop.hbase.HConstants;
037import org.apache.hadoop.hbase.HRegionLocation;
038import org.apache.hadoop.hbase.ServerName;
039import org.apache.hadoop.hbase.TableExistsException;
040import org.apache.hadoop.hbase.TableName;
041import org.apache.hadoop.hbase.TableNotFoundException;
042import org.apache.hadoop.hbase.master.LoadBalancer;
043import org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTrackerFactory;
044import org.apache.hadoop.hbase.testclassification.ClientTests;
045import org.apache.hadoop.hbase.testclassification.LargeTests;
046import org.apache.hadoop.hbase.util.Bytes;
047import org.junit.ClassRule;
048import org.junit.Test;
049import org.junit.experimental.categories.Category;
050import org.junit.runner.RunWith;
051import org.junit.runners.Parameterized;
052
053/**
054 * Class to test asynchronous table admin operations.
055 * @see TestAsyncTableAdminApi2 This test and it used to be joined it was taking longer than our ten
056 *      minute timeout so they were split.
057 * @see TestAsyncTableAdminApi3 Another split out from this class so each runs under ten minutes.
058 */
059@RunWith(Parameterized.class)
060@Category({ LargeTests.class, ClientTests.class })
061public class TestAsyncTableAdminApi extends TestAsyncAdminBase {
062
063  @ClassRule
064  public static final HBaseClassTestRule CLASS_RULE =
065    HBaseClassTestRule.forClass(TestAsyncTableAdminApi.class);
066
067  @Test
068  public void testCreateTable() throws Exception {
069    List<TableDescriptor> tables = admin.listTableDescriptors().get();
070    int numTables = tables.size();
071    createTableWithDefaultConf(tableName);
072    tables = admin.listTableDescriptors().get();
073    assertEquals(numTables + 1, tables.size());
074    assertTrue("Table must be enabled.", TEST_UTIL.getHBaseCluster().getMaster()
075      .getTableStateManager().isTableState(tableName, TableState.State.ENABLED));
076    assertEquals(TableState.State.ENABLED, getStateFromMeta(tableName));
077  }
078
079  static TableState.State getStateFromMeta(TableName table) throws Exception {
080    Optional<TableState> state = AsyncMetaTableAccessor
081      .getTableState(ASYNC_CONN.getTable(TableName.META_TABLE_NAME), table).get();
082    assertTrue(state.isPresent());
083    return state.get().getState();
084  }
085
086  @Test
087  public void testCreateTableNumberOfRegions() throws Exception {
088    AsyncTable<AdvancedScanResultConsumer> metaTable = ASYNC_CONN.getTable(META_TABLE_NAME);
089
090    createTableWithDefaultConf(tableName);
091    List<HRegionLocation> regionLocations =
092      AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, tableName).get();
093    assertEquals("Table should have only 1 region", 1, regionLocations.size());
094
095    final TableName tableName2 = TableName.valueOf(tableName.getNameAsString() + "_2");
096    createTableWithDefaultConf(tableName2, new byte[][] { new byte[] { 42 } });
097    regionLocations = AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, tableName2).get();
098    assertEquals("Table should have only 2 region", 2, regionLocations.size());
099
100    final TableName tableName3 = TableName.valueOf(tableName.getNameAsString() + "_3");
101    TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName3);
102    builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(FAMILY));
103    admin.createTable(builder.build(), Bytes.toBytes("a"), Bytes.toBytes("z"), 3).join();
104    regionLocations = AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, tableName3).get();
105    assertEquals("Table should have only 3 region", 3, regionLocations.size());
106
107    final TableName tableName4 = TableName.valueOf(tableName.getNameAsString() + "_4");
108    builder = TableDescriptorBuilder.newBuilder(tableName4);
109    builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(FAMILY));
110    try {
111      admin.createTable(builder.build(), "a".getBytes(), "z".getBytes(), 2).join();
112      fail("Should not be able to create a table with only 2 regions using this API.");
113    } catch (CompletionException e) {
114      assertTrue(e.getCause() instanceof IllegalArgumentException);
115    }
116
117    final TableName tableName5 = TableName.valueOf(tableName.getNameAsString() + "_5");
118    builder = TableDescriptorBuilder.newBuilder(tableName5);
119    builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(FAMILY));
120    admin.createTable(builder.build(), new byte[] { 1 }, new byte[] { 127 }, 16).join();
121    regionLocations = AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, tableName5).get();
122    assertEquals("Table should have 16 region", 16, regionLocations.size());
123  }
124
125  @Test
126  public void testCreateTableWithRegions() throws Exception {
127    byte[][] splitKeys = { new byte[] { 1, 1, 1 }, new byte[] { 2, 2, 2 }, new byte[] { 3, 3, 3 },
128      new byte[] { 4, 4, 4 }, new byte[] { 5, 5, 5 }, new byte[] { 6, 6, 6 },
129      new byte[] { 7, 7, 7 }, new byte[] { 8, 8, 8 }, new byte[] { 9, 9, 9 }, };
130    int expectedRegions = splitKeys.length + 1;
131    boolean tablesOnMaster = LoadBalancer.isTablesOnMaster(TEST_UTIL.getConfiguration());
132    createTableWithDefaultConf(tableName, splitKeys);
133
134    boolean tableAvailable = admin.isTableAvailable(tableName, splitKeys).get();
135    assertTrue("Table should be created with splitKyes + 1 rows in META", tableAvailable);
136
137    AsyncTable<AdvancedScanResultConsumer> metaTable = ASYNC_CONN.getTable(META_TABLE_NAME);
138    List<HRegionLocation> regions =
139      AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, tableName).get();
140    Iterator<HRegionLocation> hris = regions.iterator();
141
142    assertEquals(
143      "Tried to create " + expectedRegions + " regions " + "but only found " + regions.size(),
144      expectedRegions, regions.size());
145    System.err.println("Found " + regions.size() + " regions");
146
147    RegionInfo hri;
148    hris = regions.iterator();
149    hri = hris.next().getRegion();
150    assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0);
151    assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[0]));
152    hri = hris.next().getRegion();
153    assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[0]));
154    assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[1]));
155    hri = hris.next().getRegion();
156    assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[1]));
157    assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[2]));
158    hri = hris.next().getRegion();
159    assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[2]));
160    assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[3]));
161    hri = hris.next().getRegion();
162    assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[3]));
163    assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[4]));
164    hri = hris.next().getRegion();
165    assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[4]));
166    assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[5]));
167    hri = hris.next().getRegion();
168    assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[5]));
169    assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[6]));
170    hri = hris.next().getRegion();
171    assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[6]));
172    assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[7]));
173    hri = hris.next().getRegion();
174    assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[7]));
175    assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[8]));
176    hri = hris.next().getRegion();
177    assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[8]));
178    assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0);
179    if (tablesOnMaster) {
180      verifyRoundRobinDistribution(regions, expectedRegions);
181    }
182
183    // Now test using start/end with a number of regions
184
185    // Use 80 bit numbers to make sure we aren't limited
186    byte[] startKey = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
187    byte[] endKey = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
188
189    // Splitting into 10 regions, we expect (null,1) ... (9, null)
190    // with (1,2) (2,3) (3,4) (4,5) (5,6) (6,7) (7,8) (8,9) in the middle
191    expectedRegions = 10;
192    final TableName tableName2 = TableName.valueOf(tableName.getNameAsString() + "_2");
193    TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName2);
194    builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(FAMILY));
195    admin.createTable(builder.build(), startKey, endKey, expectedRegions).join();
196
197    regions = AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, tableName2).get();
198    assertEquals(
199      "Tried to create " + expectedRegions + " regions " + "but only found " + regions.size(),
200      expectedRegions, regions.size());
201    System.err.println("Found " + regions.size() + " regions");
202
203    hris = regions.iterator();
204    hri = hris.next().getRegion();
205    assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0);
206    assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }));
207    hri = hris.next().getRegion();
208    assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }));
209    assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }));
210    hri = hris.next().getRegion();
211    assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }));
212    assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }));
213    hri = hris.next().getRegion();
214    assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }));
215    assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }));
216    hri = hris.next().getRegion();
217    assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }));
218    assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }));
219    hri = hris.next().getRegion();
220    assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }));
221    assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }));
222    hri = hris.next().getRegion();
223    assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }));
224    assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 }));
225    hri = hris.next().getRegion();
226    assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 }));
227    assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }));
228    hri = hris.next().getRegion();
229    assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }));
230    assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }));
231    hri = hris.next().getRegion();
232    assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }));
233    assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0);
234    if (tablesOnMaster) {
235      // This don't work if master is not carrying regions. FIX. TODO.
236      verifyRoundRobinDistribution(regions, expectedRegions);
237    }
238
239    // Try once more with something that divides into something infinite
240    startKey = new byte[] { 0, 0, 0, 0, 0, 0 };
241    endKey = new byte[] { 1, 0, 0, 0, 0, 0 };
242
243    expectedRegions = 5;
244    final TableName tableName3 = TableName.valueOf(tableName.getNameAsString() + "_3");
245    builder = TableDescriptorBuilder.newBuilder(tableName3);
246    builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(FAMILY));
247    admin.createTable(builder.build(), startKey, endKey, expectedRegions).join();
248
249    regions = AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, tableName3).get();
250    assertEquals(
251      "Tried to create " + expectedRegions + " regions " + "but only found " + regions.size(),
252      expectedRegions, regions.size());
253    System.err.println("Found " + regions.size() + " regions");
254    if (tablesOnMaster) {
255      // This don't work if master is not carrying regions. FIX. TODO.
256      verifyRoundRobinDistribution(regions, expectedRegions);
257    }
258
259    // Try an invalid case where there are duplicate split keys
260    splitKeys = new byte[][] { new byte[] { 1, 1, 1 }, new byte[] { 2, 2, 2 },
261      new byte[] { 3, 3, 3 }, new byte[] { 2, 2, 2 } };
262    final TableName tableName4 = TableName.valueOf(tableName.getNameAsString() + "_4");
263    try {
264      createTableWithDefaultConf(tableName4, splitKeys);
265      fail("Should not be able to create this table because of " + "duplicate split keys");
266    } catch (CompletionException e) {
267      assertTrue(e.getCause() instanceof IllegalArgumentException);
268    }
269  }
270
271  private void verifyRoundRobinDistribution(List<HRegionLocation> regions, int expectedRegions) {
272    int numRS = TEST_UTIL.getMiniHBaseCluster().getNumLiveRegionServers();
273
274    Map<ServerName, List<RegionInfo>> server2Regions = new HashMap<>();
275    regions.stream().forEach((loc) -> {
276      ServerName server = loc.getServerName();
277      server2Regions.computeIfAbsent(server, (s) -> new ArrayList<>()).add(loc.getRegion());
278    });
279    if (numRS >= 2) {
280      // Ignore the master region server,
281      // which contains less regions by intention.
282      numRS--;
283    }
284    float average = (float) expectedRegions / numRS;
285    int min = (int) Math.floor(average);
286    int max = (int) Math.ceil(average);
287    server2Regions.values().forEach((regionList) -> {
288      assertTrue(regionList.size() == min || regionList.size() == max);
289    });
290  }
291
292  @Test
293  public void testCreateTableWithOnlyEmptyStartRow() throws Exception {
294    byte[][] splitKeys = new byte[1][];
295    splitKeys[0] = HConstants.EMPTY_BYTE_ARRAY;
296    try {
297      createTableWithDefaultConf(tableName, splitKeys);
298      fail("Test case should fail as empty split key is passed.");
299    } catch (CompletionException e) {
300      assertTrue(e.getCause() instanceof IllegalArgumentException);
301    }
302  }
303
304  @Test
305  public void testCreateTableWithEmptyRowInTheSplitKeys() throws Exception {
306    byte[][] splitKeys = new byte[3][];
307    splitKeys[0] = "region1".getBytes();
308    splitKeys[1] = HConstants.EMPTY_BYTE_ARRAY;
309    splitKeys[2] = "region2".getBytes();
310    try {
311      createTableWithDefaultConf(tableName, splitKeys);
312      fail("Test case should fail as empty split key is passed.");
313    } catch (CompletionException e) {
314      assertTrue(e.getCause() instanceof IllegalArgumentException);
315    }
316  }
317
318  @Test
319  public void testDeleteTable() throws Exception {
320    createTableWithDefaultConf(tableName);
321    assertTrue(admin.tableExists(tableName).get());
322    TEST_UTIL.getAdmin().disableTable(tableName);
323    admin.deleteTable(tableName).join();
324    assertFalse(admin.tableExists(tableName).get());
325  }
326
327  @Test
328  public void testTruncateTable() throws Exception {
329    testTruncateTable(tableName, false);
330  }
331
332  @Test
333  public void testTruncateTablePreservingSplits() throws Exception {
334    testTruncateTable(tableName, true);
335  }
336
337  private void testTruncateTable(final TableName tableName, boolean preserveSplits)
338    throws Exception {
339    byte[][] splitKeys = new byte[2][];
340    splitKeys[0] = Bytes.toBytes(4);
341    splitKeys[1] = Bytes.toBytes(8);
342
343    // Create & Fill the table
344    createTableWithDefaultConf(tableName, splitKeys);
345    AsyncTable<?> table = ASYNC_CONN.getTable(tableName);
346    int expectedRows = 10;
347    for (int i = 0; i < expectedRows; i++) {
348      byte[] data = Bytes.toBytes(String.valueOf(i));
349      Put put = new Put(data);
350      put.addColumn(FAMILY, null, data);
351      table.put(put).join();
352    }
353    assertEquals(10, table.scanAll(new Scan()).get().size());
354    assertEquals(3, TEST_UTIL.getHBaseCluster().getRegions(tableName).size());
355
356    // Truncate & Verify
357    admin.disableTable(tableName).join();
358    admin.truncateTable(tableName, preserveSplits).join();
359    assertEquals(0, table.scanAll(new Scan()).get().size());
360    if (preserveSplits) {
361      assertEquals(3, TEST_UTIL.getHBaseCluster().getRegions(tableName).size());
362    } else {
363      assertEquals(1, TEST_UTIL.getHBaseCluster().getRegions(tableName).size());
364    }
365  }
366
367  @Test
368  public void testCloneTableSchema() throws Exception {
369    final TableName newTableName = TableName.valueOf(tableName.getNameAsString() + "_new");
370    testCloneTableSchema(tableName, newTableName, false);
371  }
372
373  @Test
374  public void testCloneTableSchemaPreservingSplits() throws Exception {
375    final TableName newTableName = TableName.valueOf(tableName.getNameAsString() + "_new");
376    testCloneTableSchema(tableName, newTableName, true);
377  }
378
379  private void testCloneTableSchema(final TableName tableName, final TableName newTableName,
380    boolean preserveSplits) throws Exception {
381    byte[][] splitKeys = new byte[2][];
382    splitKeys[0] = Bytes.toBytes(4);
383    splitKeys[1] = Bytes.toBytes(8);
384    int NUM_FAMILYS = 2;
385    int NUM_REGIONS = 3;
386    int BLOCK_SIZE = 1024;
387    int TTL = 86400;
388    boolean BLOCK_CACHE = false;
389
390    // Create the table
391    TableDescriptor tableDesc = TableDescriptorBuilder.newBuilder(tableName)
392      .setColumnFamily(ColumnFamilyDescriptorBuilder.of(FAMILY_0))
393      .setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(FAMILY_1).setBlocksize(BLOCK_SIZE)
394        .setBlockCacheEnabled(BLOCK_CACHE).setTimeToLive(TTL).build())
395      .build();
396    admin.createTable(tableDesc, splitKeys).join();
397
398    assertEquals(NUM_REGIONS, TEST_UTIL.getHBaseCluster().getRegions(tableName).size());
399    assertTrue("Table should be created with splitKyes + 1 rows in META",
400      admin.isTableAvailable(tableName, splitKeys).get());
401
402    // Clone & Verify
403    admin.cloneTableSchema(tableName, newTableName, preserveSplits).join();
404    TableDescriptor newTableDesc = admin.getDescriptor(newTableName).get();
405
406    assertEquals(NUM_FAMILYS, newTableDesc.getColumnFamilyCount());
407    assertEquals(BLOCK_SIZE, newTableDesc.getColumnFamily(FAMILY_1).getBlocksize());
408    assertEquals(BLOCK_CACHE, newTableDesc.getColumnFamily(FAMILY_1).isBlockCacheEnabled());
409    assertEquals(TTL, newTableDesc.getColumnFamily(FAMILY_1).getTimeToLive());
410    // HBASE-26246 introduced persist of store file tracker into table descriptor
411    tableDesc = TableDescriptorBuilder.newBuilder(tableDesc).setValue(TRACKER_IMPL,
412      StoreFileTrackerFactory.getStoreFileTrackerName(TEST_UTIL.getConfiguration())).build();
413    TEST_UTIL.verifyTableDescriptorIgnoreTableName(tableDesc, newTableDesc);
414
415    if (preserveSplits) {
416      assertEquals(NUM_REGIONS, TEST_UTIL.getHBaseCluster().getRegions(newTableName).size());
417      assertTrue("New table should be created with splitKyes + 1 rows in META",
418        admin.isTableAvailable(newTableName, splitKeys).get());
419    } else {
420      assertEquals(1, TEST_UTIL.getHBaseCluster().getRegions(newTableName).size());
421    }
422  }
423
424  @Test
425  public void testCloneTableSchemaWithNonExistentSourceTable() throws Exception {
426    final TableName newTableName = TableName.valueOf(tableName.getNameAsString() + "_new");
427    // test for non-existent source table
428    try {
429      admin.cloneTableSchema(tableName, newTableName, false).join();
430      fail("Should have failed when source table doesn't exist.");
431    } catch (CompletionException e) {
432      assertTrue(e.getCause() instanceof TableNotFoundException);
433    }
434  }
435
436  @Test
437  public void testCloneTableSchemaWithExistentDestinationTable() throws Exception {
438    final TableName newTableName = TableName.valueOf(tableName.getNameAsString() + "_new");
439    byte[] FAMILY_0 = Bytes.toBytes("cf0");
440    TEST_UTIL.createTable(tableName, FAMILY_0);
441    TEST_UTIL.createTable(newTableName, FAMILY_0);
442    // test for existent destination table
443    try {
444      admin.cloneTableSchema(tableName, newTableName, false).join();
445      fail("Should have failed when destination table exists.");
446    } catch (CompletionException e) {
447      assertTrue(e.getCause() instanceof TableExistsException);
448    }
449  }
450
451  @Test
452  public void testIsTableAvailableWithInexistantTable() throws Exception {
453    final TableName newTableName = TableName.valueOf(tableName.getNameAsString() + "_new");
454    // test for inexistant table
455    assertFalse(admin.isTableAvailable(newTableName).get());
456  }
457}