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.thrift2;
019
020import static org.apache.hadoop.hbase.thrift.Constants.THRIFT_INFO_SERVER_PORT;
021import static org.junit.jupiter.api.Assertions.assertEquals;
022import static org.junit.jupiter.api.Assertions.assertFalse;
023import static org.junit.jupiter.api.Assertions.assertNotNull;
024import static org.junit.jupiter.api.Assertions.assertNull;
025import static org.junit.jupiter.api.Assertions.assertTrue;
026
027import java.io.IOException;
028import java.util.ArrayList;
029import java.util.Collections;
030import java.util.Iterator;
031import java.util.List;
032import org.apache.hadoop.conf.Configuration;
033import org.apache.hadoop.hbase.Cell;
034import org.apache.hadoop.hbase.CellUtil;
035import org.apache.hadoop.hbase.CompareOperator;
036import org.apache.hadoop.hbase.HBaseConfiguration;
037import org.apache.hadoop.hbase.HBaseTestingUtil;
038import org.apache.hadoop.hbase.HConstants;
039import org.apache.hadoop.hbase.NamespaceDescriptor;
040import org.apache.hadoop.hbase.TableName;
041import org.apache.hadoop.hbase.client.Admin;
042import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
043import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
044import org.apache.hadoop.hbase.client.Connection;
045import org.apache.hadoop.hbase.client.ConnectionFactory;
046import org.apache.hadoop.hbase.client.ConnectionUtils;
047import org.apache.hadoop.hbase.client.Delete;
048import org.apache.hadoop.hbase.client.Durability;
049import org.apache.hadoop.hbase.client.Get;
050import org.apache.hadoop.hbase.client.Put;
051import org.apache.hadoop.hbase.client.Result;
052import org.apache.hadoop.hbase.client.ResultScanner;
053import org.apache.hadoop.hbase.client.Scan;
054import org.apache.hadoop.hbase.client.Table;
055import org.apache.hadoop.hbase.client.TableDescriptor;
056import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
057import org.apache.hadoop.hbase.filter.ColumnCountGetFilter;
058import org.apache.hadoop.hbase.filter.ColumnValueFilter;
059import org.apache.hadoop.hbase.filter.FilterList;
060import org.apache.hadoop.hbase.filter.PrefixFilter;
061import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
062import org.apache.hadoop.hbase.testclassification.LargeTests;
063import org.apache.hadoop.hbase.testclassification.RestTests;
064import org.apache.hadoop.hbase.thrift.Constants;
065import org.apache.hadoop.hbase.thrift2.client.ThriftConnection;
066import org.apache.hadoop.hbase.util.Bytes;
067import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
068import org.junit.jupiter.api.AfterAll;
069import org.junit.jupiter.api.BeforeAll;
070import org.junit.jupiter.api.Tag;
071import org.junit.jupiter.api.Test;
072import org.slf4j.Logger;
073import org.slf4j.LoggerFactory;
074
075@Tag(RestTests.TAG)
076@Tag(LargeTests.TAG)
077public class TestThriftConnection {
078  private static final Logger LOG = LoggerFactory.getLogger(TestThriftConnection.class);
079
080  private static final byte[] FAMILYA = Bytes.toBytes("fa");
081  private static final byte[] FAMILYB = Bytes.toBytes("fb");
082  private static final byte[] FAMILYC = Bytes.toBytes("fc");
083  private static final byte[] FAMILYD = Bytes.toBytes("fd");
084
085  private static final byte[] ROW_1 = Bytes.toBytes("testrow1");
086  private static final byte[] ROW_2 = Bytes.toBytes("testrow2");
087  private static final byte[] ROW_3 = Bytes.toBytes("testrow3");
088  private static final byte[] ROW_4 = Bytes.toBytes("testrow4");
089
090  private static final byte[] QUALIFIER_1 = Bytes.toBytes("1");
091  private static final byte[] QUALIFIER_2 = Bytes.toBytes("2");
092  private static final byte[] VALUE_1 = Bytes.toBytes("testvalue1");
093  private static final byte[] VALUE_2 = Bytes.toBytes("testvalue2");
094
095  private static final long ONE_HOUR = 60 * 60 * 1000;
096  private static final long TS_2 = EnvironmentEdgeManager.currentTime();
097  private static final long TS_1 = TS_2 - ONE_HOUR;
098
099  protected static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
100
101  protected static ThriftServer thriftServer;
102
103  protected static ThriftServer thriftHttpServer;
104
105  protected static int thriftPort;
106  protected static int httpPort;
107
108  protected static Connection thriftConnection;
109  protected static Connection thriftHttpConnection;
110
111  private static Admin thriftAdmin;
112
113  private static ThriftServer startThriftServer(int port, boolean useHttp) {
114    Configuration thriftServerConf = HBaseConfiguration.create(TEST_UTIL.getConfiguration());
115    thriftServerConf.setInt(Constants.PORT_CONF_KEY, port);
116    if (useHttp) {
117      thriftServerConf.setBoolean(Constants.USE_HTTP_CONF_KEY, true);
118    }
119    ThriftServer server = new ThriftServer(thriftServerConf);
120    Thread thriftServerThread = new Thread(() -> {
121      try {
122        server.run();
123      } catch (Exception t) {
124        LOG.error("Thrift Server failed", t);
125      }
126    });
127    thriftServerThread.setDaemon(true);
128    thriftServerThread.start();
129    if (useHttp) {
130      TEST_UTIL.waitFor(10000, () -> server.getHttpServer() != null);
131    } else {
132      TEST_UTIL.waitFor(10000, () -> server.getTserver() != null);
133    }
134    return server;
135  }
136
137  private static Connection createConnection(int port, boolean useHttp) throws IOException {
138    Configuration conf = HBaseConfiguration.create(TEST_UTIL.getConfiguration());
139    conf.set(ConnectionUtils.HBASE_CLIENT_CONNECTION_IMPL, ThriftConnection.class.getName());
140    if (useHttp) {
141      conf.set(Constants.HBASE_THRIFT_CLIENT_BUIDLER_CLASS,
142        ThriftConnection.HTTPThriftClientBuilder.class.getName());
143    }
144    String host = HConstants.LOCALHOST;
145    if (useHttp) {
146      host = "http://" + host;
147    }
148    conf.set(Constants.HBASE_THRIFT_SERVER_NAME, host);
149    conf.setInt(Constants.HBASE_THRIFT_SERVER_PORT, port);
150    return ConnectionFactory.createConnection(conf);
151  }
152
153  @BeforeAll
154  public static void setUp() throws Exception {
155    // Do not start info server
156    TEST_UTIL.getConfiguration().setInt(THRIFT_INFO_SERVER_PORT, -1);
157    TEST_UTIL.startMiniCluster();
158    thriftPort = HBaseTestingUtil.randomFreePort();
159    httpPort = HBaseTestingUtil.randomFreePort();
160    // Start a thrift server
161    thriftServer = startThriftServer(thriftPort, false);
162    // Start an HTTP thrift server
163    thriftHttpServer = startThriftServer(httpPort, true);
164    thriftConnection = createConnection(thriftPort, false);
165    thriftHttpConnection = createConnection(httpPort, true);
166    thriftAdmin = thriftConnection.getAdmin();
167    LOG.info("TS_1=" + TS_1);
168    LOG.info("TS_2=" + TS_1);
169
170  }
171
172  @AfterAll
173  public static void shutdown() throws Exception {
174    if (thriftAdmin != null) {
175      thriftAdmin.close();
176    }
177    if (thriftHttpConnection != null) {
178      thriftHttpConnection.close();
179    }
180    if (thriftConnection != null) {
181      thriftConnection.close();
182    }
183    if (thriftHttpServer != null) {
184      thriftHttpServer.stop();
185    }
186    TEST_UTIL.shutdownMiniCluster();
187  }
188
189  @Test
190  public void testGetClusterId() {
191    String actualClusterId = TEST_UTIL.getMiniHBaseCluster().getMaster().getClusterId();
192    for (Connection conn : new Connection[] { thriftConnection, thriftHttpConnection }) {
193      String thriftClusterId = conn.getClusterId();
194      assertEquals(actualClusterId, thriftClusterId);
195    }
196  }
197
198  @Test
199  public void testThriftAdmin() throws Exception {
200    testThriftAdmin(thriftConnection, "testThriftAdminNamespace", "testThriftAdminTable");
201    testThriftAdmin(thriftHttpConnection, "testThriftHttpAdminNamespace",
202      "testThriftHttpAdminTable");
203  }
204
205  @Test
206  public void testGet() throws Exception {
207    testGet(thriftConnection, "testGetTable");
208    testGet(thriftHttpConnection, "testGetHttpTable");
209
210  }
211
212  private void testGet(Connection connection, String tableName) throws IOException {
213    createTable(thriftAdmin, tableName);
214    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
215      Get get = new Get(ROW_1);
216      Result result = table.get(get);
217      byte[] value1 = result.getValue(FAMILYA, QUALIFIER_1);
218      byte[] value2 = result.getValue(FAMILYB, QUALIFIER_2);
219      assertNotNull(value1);
220      assertTrue(Bytes.equals(VALUE_1, value1));
221      assertNull(value2);
222
223      get = new Get(ROW_1);
224      get.addFamily(FAMILYC);
225      result = table.get(get);
226      value1 = result.getValue(FAMILYA, QUALIFIER_1);
227      value2 = result.getValue(FAMILYB, QUALIFIER_2);
228      assertNull(value1);
229      assertNull(value2);
230
231      get = new Get(ROW_1);
232      get.addColumn(FAMILYA, QUALIFIER_1);
233      get.addColumn(FAMILYB, QUALIFIER_2);
234      result = table.get(get);
235      value1 = result.getValue(FAMILYA, QUALIFIER_1);
236      value2 = result.getValue(FAMILYB, QUALIFIER_2);
237      assertNotNull(value1);
238      assertTrue(Bytes.equals(VALUE_1, value1));
239      assertNull(value2);
240
241      get = new Get(ROW_2);
242      result = table.get(get);
243      value1 = result.getValue(FAMILYA, QUALIFIER_1);
244      value2 = result.getValue(FAMILYB, QUALIFIER_2);
245      assertNotNull(value1);
246      assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
247      assertNotNull(value2);
248      assertTrue(Bytes.equals(VALUE_2, value2));
249
250      get = new Get(ROW_2);
251      get.addFamily(FAMILYA);
252      result = table.get(get);
253      value1 = result.getValue(FAMILYA, QUALIFIER_1);
254      value2 = result.getValue(FAMILYB, QUALIFIER_2);
255      assertNotNull(value1);
256      assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
257      assertNull(value2);
258
259      get = new Get(ROW_2);
260      get.addColumn(FAMILYA, QUALIFIER_1);
261      get.addColumn(FAMILYB, QUALIFIER_2);
262      result = table.get(get);
263      value1 = result.getValue(FAMILYA, QUALIFIER_1);
264      value2 = result.getValue(FAMILYB, QUALIFIER_2);
265      assertNotNull(value1);
266      assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
267      assertNotNull(value2);
268      assertTrue(Bytes.equals(VALUE_2, value2));
269
270      // test timestamp
271
272      get = new Get(ROW_2);
273      get.addFamily(FAMILYA);
274      get.addFamily(FAMILYB);
275      get.setTimestamp(TS_1);
276      result = table.get(get);
277      value1 = result.getValue(FAMILYA, QUALIFIER_1);
278      value2 = result.getValue(FAMILYB, QUALIFIER_2);
279      assertNotNull(value1);
280      assertTrue(Bytes.equals(VALUE_1, value1)); // @TS_1
281      assertNull(value2);
282
283      // test timerange
284
285      get = new Get(ROW_2);
286      get.addFamily(FAMILYA);
287      get.addFamily(FAMILYB);
288      get.setTimeRange(0, TS_1 + 1);
289      result = table.get(get);
290      value1 = result.getValue(FAMILYA, QUALIFIER_1);
291      value2 = result.getValue(FAMILYB, QUALIFIER_2);
292      assertNotNull(value1);
293      assertTrue(Bytes.equals(VALUE_1, value1)); // @TS_1
294      assertNull(value2);
295
296      // test maxVersions
297
298      get = new Get(ROW_2);
299      get.addFamily(FAMILYA);
300      get.readVersions(2);
301      result = table.get(get);
302      int count = 0;
303      for (Cell kv : result.listCells()) {
304        if (CellUtil.matchingFamily(kv, FAMILYA) && TS_1 == kv.getTimestamp()) {
305          assertTrue(CellUtil.matchingValue(kv, VALUE_1)); // @TS_1
306          count++;
307        }
308        if (CellUtil.matchingFamily(kv, FAMILYA) && TS_2 == kv.getTimestamp()) {
309          assertTrue(CellUtil.matchingValue(kv, VALUE_2)); // @TS_2
310          count++;
311        }
312      }
313      assertEquals(2, count);
314    }
315
316  }
317
318  @Test
319  public void testHBASE22011() throws Exception {
320    testHBASE22011(thriftConnection, "testHBASE22011Table");
321    testHBASE22011(thriftHttpConnection, "testHBASE22011HttpTable");
322  }
323
324  public void testHBASE22011(Connection connection, String tableName) throws IOException {
325    createTable(thriftAdmin, tableName);
326    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
327      Get get = new Get(ROW_2);
328      Result result = table.get(get);
329      assertEquals(2, result.listCells().size());
330
331      ColumnCountGetFilter filter = new ColumnCountGetFilter(1);
332      get.setFilter(filter);
333      result = table.get(get);
334      assertEquals(1, result.listCells().size());
335    }
336  }
337
338  @Test
339  public void testMultiGet() throws Exception {
340    testMultiGet(thriftConnection, "testMultiGetTable");
341    testMultiGet(thriftHttpConnection, "testMultiGetHttpTable");
342  }
343
344  public void testMultiGet(Connection connection, String tableName) throws Exception {
345    createTable(thriftAdmin, tableName);
346    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
347      ArrayList<Get> gets = new ArrayList<>(2);
348      gets.add(new Get(ROW_1));
349      gets.add(new Get(ROW_2));
350      Result[] results = table.get(gets);
351      assertNotNull(results);
352      assertEquals(2, results.length);
353      assertEquals(1, results[0].size());
354      assertEquals(2, results[1].size());
355
356      // Test Versions
357      gets = new ArrayList<>(2);
358      Get g = new Get(ROW_1);
359      g.readVersions(3);
360      gets.add(g);
361      Get get2 = new Get(ROW_2);
362      get2.readVersions(3);
363      gets.add(get2);
364      results = table.get(gets);
365      assertNotNull(results);
366      assertEquals(2, results.length);
367      assertEquals(1, results[0].size());
368      assertEquals(3, results[1].size());
369
370      gets = new ArrayList<>(1);
371      gets.add(new Get(Bytes.toBytes("RESALLYREALLYNOTTHERE")));
372      results = table.get(gets);
373      assertNotNull(results);
374      assertTrue(results[0].isEmpty());
375
376      gets = new ArrayList<>(3);
377      gets.add(new Get(Bytes.toBytes("RESALLYREALLYNOTTHERE")));
378      gets.add(new Get(ROW_1));
379      gets.add(new Get(ROW_2));
380      results = table.get(gets);
381      assertNotNull(results);
382      assertEquals(3, results.length);
383      assertTrue(results[0].isEmpty());
384    }
385
386  }
387
388  @Test
389  public void testPut() throws Exception {
390    testPut(thriftConnection, "testPutTable");
391    testPut(thriftHttpConnection, "testPutHttpTable");
392  }
393
394  public void testPut(Connection connection, String tableName) throws IOException {
395    createTable(thriftAdmin, tableName);
396    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
397      Put put = new Put(ROW_3);
398      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
399      table.put(put);
400
401      Get get = new Get(ROW_3);
402      get.addFamily(FAMILYA);
403      Result result = table.get(get);
404      byte[] value = result.getValue(FAMILYA, QUALIFIER_1);
405      assertNotNull(value);
406      assertTrue(Bytes.equals(VALUE_1, value));
407
408      // multiput
409
410      List<Put> puts = new ArrayList<>(3);
411      put = new Put(ROW_3);
412      put.addColumn(FAMILYB, QUALIFIER_2, VALUE_2);
413      puts.add(put);
414      put = new Put(ROW_4);
415      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
416      puts.add(put);
417      put = new Put(ROW_4);
418      put.addColumn(FAMILYB, QUALIFIER_2, VALUE_2);
419      puts.add(put);
420      table.put(puts);
421
422      get = new Get(ROW_3);
423      get.addFamily(FAMILYB);
424      result = table.get(get);
425      value = result.getValue(FAMILYB, QUALIFIER_2);
426      assertNotNull(value);
427      assertTrue(Bytes.equals(VALUE_2, value));
428      get = new Get(ROW_4);
429      result = table.get(get);
430      value = result.getValue(FAMILYA, QUALIFIER_1);
431      assertNotNull(value);
432      assertTrue(Bytes.equals(VALUE_1, value));
433      value = result.getValue(FAMILYB, QUALIFIER_2);
434      assertNotNull(value);
435      assertTrue(Bytes.equals(VALUE_2, value));
436    }
437  }
438
439  @Test
440  public void testDelete() throws Exception {
441    testDelete(thriftConnection, "testDeleteTable");
442    testDelete(thriftHttpConnection, "testDeleteHttpTable");
443  }
444
445  public void testDelete(Connection connection, String tableName) throws IOException {
446    createTable(thriftAdmin, tableName);
447    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
448      Put put = new Put(ROW_3);
449      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
450      put.addColumn(FAMILYB, QUALIFIER_2, VALUE_2);
451      put.addColumn(FAMILYC, QUALIFIER_1, VALUE_1);
452      put.addColumn(FAMILYC, QUALIFIER_2, VALUE_2);
453      table.put(put);
454
455      Get get = new Get(ROW_3);
456      get.addFamily(FAMILYA);
457      get.addFamily(FAMILYB);
458      get.addFamily(FAMILYC);
459      Result result = table.get(get);
460      byte[] value1 = result.getValue(FAMILYA, QUALIFIER_1);
461      byte[] value2 = result.getValue(FAMILYB, QUALIFIER_2);
462      byte[] value3 = result.getValue(FAMILYC, QUALIFIER_1);
463      byte[] value4 = result.getValue(FAMILYC, QUALIFIER_2);
464      assertNotNull(value1);
465      assertTrue(Bytes.equals(VALUE_1, value1));
466      assertNotNull(value2);
467      assertTrue(Bytes.equals(VALUE_2, value2));
468      assertNotNull(value3);
469      assertTrue(Bytes.equals(VALUE_1, value3));
470      assertNotNull(value4);
471      assertTrue(Bytes.equals(VALUE_2, value4));
472
473      Delete delete = new Delete(ROW_3);
474      delete.addColumn(FAMILYB, QUALIFIER_2);
475      table.delete(delete);
476
477      get = new Get(ROW_3);
478      get.addFamily(FAMILYA);
479      get.addFamily(FAMILYB);
480      result = table.get(get);
481      value1 = result.getValue(FAMILYA, QUALIFIER_1);
482      value2 = result.getValue(FAMILYB, QUALIFIER_2);
483      assertNotNull(value1);
484      assertTrue(Bytes.equals(VALUE_1, value1));
485      assertNull(value2);
486
487      delete = new Delete(ROW_3);
488      delete.setTimestamp(1L);
489      table.delete(delete);
490
491      get = new Get(ROW_3);
492      get.addFamily(FAMILYA);
493      get.addFamily(FAMILYB);
494      result = table.get(get);
495      value1 = result.getValue(FAMILYA, QUALIFIER_1);
496      value2 = result.getValue(FAMILYB, QUALIFIER_2);
497      assertNotNull(value1);
498      assertTrue(Bytes.equals(VALUE_1, value1));
499      assertNull(value2);
500
501      // Delete column family from row
502      delete = new Delete(ROW_3);
503      delete.addFamily(FAMILYC);
504      table.delete(delete);
505
506      get = new Get(ROW_3);
507      get.addFamily(FAMILYC);
508      result = table.get(get);
509      value3 = result.getValue(FAMILYC, QUALIFIER_1);
510      value4 = result.getValue(FAMILYC, QUALIFIER_2);
511      assertNull(value3);
512      assertNull(value4);
513
514      delete = new Delete(ROW_3);
515      table.delete(delete);
516
517      get = new Get(ROW_3);
518      get.addFamily(FAMILYA);
519      get.addFamily(FAMILYB);
520      result = table.get(get);
521      value1 = result.getValue(FAMILYA, QUALIFIER_1);
522      value2 = result.getValue(FAMILYB, QUALIFIER_2);
523      assertNull(value1);
524      assertNull(value2);
525    }
526
527  }
528
529  @Test
530  public void testScanner() throws Exception {
531    testScanner(thriftConnection, "testScannerTable");
532    testScanner(thriftHttpConnection, "testScannerHttpTable");
533  }
534
535  public void testScanner(Connection connection, String tableName) throws IOException {
536    createTable(thriftAdmin, tableName);
537    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
538      List<Put> puts = new ArrayList<>(4);
539      Put put = new Put(ROW_1);
540      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
541      puts.add(put);
542      put = new Put(ROW_2);
543      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
544      puts.add(put);
545      put = new Put(ROW_3);
546      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
547      puts.add(put);
548      put = new Put(ROW_4);
549      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
550      puts.add(put);
551      table.put(puts);
552
553      ResultScanner scanner = table.getScanner(new Scan());
554
555      Result[] results = scanner.next(1);
556      assertNotNull(results);
557      assertEquals(1, results.length);
558      assertTrue(Bytes.equals(ROW_1, results[0].getRow()));
559
560      Result result = scanner.next();
561      assertNotNull(result);
562      assertTrue(Bytes.equals(ROW_2, result.getRow()));
563
564      results = scanner.next(2);
565      assertNotNull(results);
566      assertEquals(2, results.length);
567      assertTrue(Bytes.equals(ROW_3, results[0].getRow()));
568      assertTrue(Bytes.equals(ROW_4, results[1].getRow()));
569
570      results = scanner.next(1);
571      assertTrue(results == null || results.length == 0);
572      scanner.close();
573
574      scanner = table.getScanner(FAMILYA);
575      results = scanner.next(4);
576      assertNotNull(results);
577      assertEquals(4, results.length);
578      assertTrue(Bytes.equals(ROW_1, results[0].getRow()));
579      assertTrue(Bytes.equals(ROW_2, results[1].getRow()));
580      assertTrue(Bytes.equals(ROW_3, results[2].getRow()));
581      assertTrue(Bytes.equals(ROW_4, results[3].getRow()));
582
583      scanner.close();
584
585      scanner = table.getScanner(FAMILYA, QUALIFIER_1);
586      results = scanner.next(4);
587      assertNotNull(results);
588      assertEquals(4, results.length);
589      assertTrue(Bytes.equals(ROW_1, results[0].getRow()));
590      assertTrue(Bytes.equals(ROW_2, results[1].getRow()));
591      assertTrue(Bytes.equals(ROW_3, results[2].getRow()));
592      assertTrue(Bytes.equals(ROW_4, results[3].getRow()));
593      scanner.close();
594    }
595
596  }
597
598  @Test
599  public void testCheckAndDelete() throws Exception {
600    testCheckAndDelete(thriftConnection, "testCheckAndDeleteTable");
601    testCheckAndDelete(thriftHttpConnection, "testCheckAndDeleteHttpTable");
602  }
603
604  public void testCheckAndDelete(Connection connection, String tableName) throws IOException {
605    createTable(thriftAdmin, tableName);
606    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
607      Get get = new Get(ROW_1);
608      Result result = table.get(get);
609      byte[] value1 = result.getValue(FAMILYA, QUALIFIER_1);
610      byte[] value2 = result.getValue(FAMILYB, QUALIFIER_2);
611      assertNotNull(value1);
612      assertTrue(Bytes.equals(VALUE_1, value1));
613      assertNull(value2);
614      assertTrue(table.exists(get));
615      assertEquals(1, table.exists(Collections.singletonList(get)).length);
616      Delete delete = new Delete(ROW_1);
617
618      table.checkAndMutate(ROW_1, FAMILYA).qualifier(QUALIFIER_1).ifEquals(VALUE_1)
619        .thenDelete(delete);
620      assertFalse(table.exists(get));
621
622      Put put = new Put(ROW_1);
623      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
624      table.put(put);
625
626      assertTrue(
627        table.checkAndMutate(ROW_1, FAMILYA).qualifier(QUALIFIER_1).ifEquals(VALUE_1).thenPut(put));
628      assertFalse(
629        table.checkAndMutate(ROW_1, FAMILYA).qualifier(QUALIFIER_1).ifEquals(VALUE_2).thenPut(put));
630    }
631
632  }
633
634  @Test
635  public void testIteratorScaner() throws Exception {
636    testIteratorScanner(thriftConnection, "testIteratorScanerTable");
637    testIteratorScanner(thriftHttpConnection, "testIteratorScanerHttpTable");
638  }
639
640  public void testIteratorScanner(Connection connection, String tableName) throws IOException {
641    createTable(thriftAdmin, tableName);
642    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
643      List<Put> puts = new ArrayList<>(4);
644      Put put = new Put(ROW_1);
645      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
646      puts.add(put);
647      put = new Put(ROW_2);
648      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
649      puts.add(put);
650      put = new Put(ROW_3);
651      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
652      puts.add(put);
653      put = new Put(ROW_4);
654      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
655      puts.add(put);
656      table.put(puts);
657      Scan scan = new Scan();
658      scan.setCaching(1);
659      ResultScanner scanner = table.getScanner(scan);
660      Iterator<Result> iterator = scanner.iterator();
661      assertTrue(iterator.hasNext());
662      int counter = 0;
663      while (iterator.hasNext()) {
664        iterator.next();
665        counter++;
666      }
667      assertEquals(4, counter);
668    }
669
670  }
671
672  @Test
673  public void testReverseScan() throws Exception {
674    testReverseScan(thriftConnection, "testReverseScanTable");
675    testReverseScan(thriftHttpConnection, "testReverseScanHttpTable");
676  }
677
678  public void testReverseScan(Connection connection, String tableName) throws IOException {
679    createTable(thriftAdmin, tableName);
680    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
681      List<Put> puts = new ArrayList<>(4);
682      Put put = new Put(ROW_1);
683      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
684      puts.add(put);
685      put = new Put(ROW_2);
686      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
687      puts.add(put);
688      put = new Put(ROW_3);
689      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
690      puts.add(put);
691      put = new Put(ROW_4);
692      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
693      puts.add(put);
694      table.put(puts);
695      Scan scan = new Scan();
696      scan.setReversed(true);
697      scan.setCaching(1);
698      ResultScanner scanner = table.getScanner(scan);
699      Iterator<Result> iterator = scanner.iterator();
700      assertTrue(iterator.hasNext());
701      int counter = 0;
702      Result lastResult = null;
703      while (iterator.hasNext()) {
704        Result current = iterator.next();
705        if (lastResult != null) {
706          assertTrue(Bytes.compareTo(lastResult.getRow(), current.getRow()) > 0);
707        }
708        lastResult = current;
709        counter++;
710      }
711      assertEquals(4, counter);
712    }
713
714  }
715
716  @Test
717  public void testScanWithFilters() throws Exception {
718    testScanWithFilters(thriftConnection, "testScanWithFiltersTable");
719    testScanWithFilters(thriftHttpConnection, "testScanWithFiltersHttpTable");
720  }
721
722  private void testScanWithFilters(Connection connection, String tableName) throws IOException {
723    createTable(thriftAdmin, tableName);
724    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
725      FilterList filterList = new FilterList();
726      PrefixFilter prefixFilter = new PrefixFilter(Bytes.toBytes("testrow"));
727      ColumnValueFilter columnValueFilter =
728        new ColumnValueFilter(FAMILYA, QUALIFIER_1, CompareOperator.EQUAL, VALUE_1);
729      filterList.addFilter(prefixFilter);
730      filterList.addFilter(columnValueFilter);
731      Scan scan = new Scan();
732      scan.readVersions(2);
733      scan.setFilter(filterList);
734      ResultScanner scanner = table.getScanner(scan);
735      Iterator<Result> iterator = scanner.iterator();
736      assertTrue(iterator.hasNext());
737      int counter = 0;
738      while (iterator.hasNext()) {
739        Result result = iterator.next();
740        counter += result.size();
741      }
742      assertEquals(2, counter);
743    }
744  }
745
746  private TableDescriptor createTable(Admin admin, String tableName) throws IOException {
747    TableDescriptorBuilder builder =
748      TableDescriptorBuilder.newBuilder(TableName.valueOf(tableName));
749    ColumnFamilyDescriptorBuilder familyABuilder =
750      ColumnFamilyDescriptorBuilder.newBuilder(FAMILYA);
751    familyABuilder.setMaxVersions(3);
752    ColumnFamilyDescriptorBuilder familyBBuilder =
753      ColumnFamilyDescriptorBuilder.newBuilder(FAMILYB);
754    familyBBuilder.setMaxVersions(3);
755    ColumnFamilyDescriptorBuilder familyCBuilder =
756      ColumnFamilyDescriptorBuilder.newBuilder(FAMILYC);
757    familyCBuilder.setMaxVersions(3);
758    builder.setColumnFamily(familyABuilder.build());
759    builder.setColumnFamily(familyBBuilder.build());
760    builder.setColumnFamily(familyCBuilder.build());
761    TableDescriptor tableDescriptor = builder.build();
762    admin.createTable(tableDescriptor);
763    try (Table table = TEST_UTIL.getConnection().getTable(TableName.valueOf(tableName))) {
764      Put put = new Put(ROW_1);
765      put.addColumn(FAMILYA, QUALIFIER_1, TS_2, VALUE_1);
766      table.put(put);
767      put = new Put(ROW_2);
768      put.addColumn(FAMILYA, QUALIFIER_1, TS_1, VALUE_1);
769      put.addColumn(FAMILYA, QUALIFIER_1, TS_2, VALUE_2);
770      put.addColumn(FAMILYB, QUALIFIER_2, TS_2, VALUE_2);
771      table.put(put);
772
773    }
774    return tableDescriptor;
775
776  }
777
778  private void testThriftAdmin(Connection connection, String namespace, String table)
779    throws Exception {
780    try (Admin admin = connection.getAdmin()) {
781      // create name space
782      NamespaceDescriptor namespaceDescriptor = NamespaceDescriptor.create(namespace).build();
783      namespaceDescriptor.setConfiguration("key1", "value1");
784      namespaceDescriptor.setConfiguration("key2", "value2");
785      admin.createNamespace(namespaceDescriptor);
786      // list namespace
787      NamespaceDescriptor[] namespaceDescriptors = admin.listNamespaceDescriptors();
788      boolean found = false;
789      for (NamespaceDescriptor nd : namespaceDescriptors) {
790        if (nd.getName().equals(namespace)) {
791          found = true;
792          break;
793        }
794      }
795      assertTrue(found);
796      // modify namesapce
797      namespaceDescriptor.setConfiguration("kye3", "value3");
798      admin.modifyNamespace(namespaceDescriptor);
799      // get namespace
800      NamespaceDescriptor namespaceDescriptorReturned = admin.getNamespaceDescriptor(namespace);
801      assertTrue(namespaceDescriptorReturned.getConfiguration().size() == 3);
802      // create table
803      TableDescriptor tableDescriptor = createTable(admin, table);
804      // modify table
805      TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableDescriptor);
806      builder.setDurability(Durability.ASYNC_WAL);
807      admin.modifyTable(builder.build());
808      // modify column family
809      ColumnFamilyDescriptor familyA = tableDescriptor.getColumnFamily(FAMILYA);
810      ColumnFamilyDescriptorBuilder familyABuilder =
811        ColumnFamilyDescriptorBuilder.newBuilder(familyA);
812      familyABuilder.setInMemory(true);
813      admin.modifyColumnFamily(tableDescriptor.getTableName(), familyABuilder.build());
814      // add column family
815      ColumnFamilyDescriptorBuilder familyDBuilder =
816        ColumnFamilyDescriptorBuilder.newBuilder(FAMILYD);
817      familyDBuilder.setDataBlockEncoding(DataBlockEncoding.PREFIX);
818      admin.addColumnFamily(tableDescriptor.getTableName(), familyDBuilder.build());
819      // get table descriptor
820      TableDescriptor tableDescriptorReturned = admin.getDescriptor(tableDescriptor.getTableName());
821      assertTrue(tableDescriptorReturned.getColumnFamilies().length == 4);
822      assertTrue(tableDescriptorReturned.getDurability() == Durability.ASYNC_WAL);
823      ColumnFamilyDescriptor columnFamilyADescriptor1Returned =
824        tableDescriptorReturned.getColumnFamily(FAMILYA);
825      assertTrue(columnFamilyADescriptor1Returned.isInMemory() == true);
826      // delete column family
827      admin.deleteColumnFamily(tableDescriptor.getTableName(), FAMILYA);
828      tableDescriptorReturned = admin.getDescriptor(tableDescriptor.getTableName());
829      assertTrue(tableDescriptorReturned.getColumnFamilies().length == 3);
830      // disable table
831      admin.disableTable(tableDescriptor.getTableName());
832      assertTrue(admin.isTableDisabled(tableDescriptor.getTableName()));
833      // enable table
834      admin.enableTable(tableDescriptor.getTableName());
835      assertTrue(admin.isTableEnabled(tableDescriptor.getTableName()));
836      assertTrue(admin.isTableAvailable(tableDescriptor.getTableName()));
837      // truncate table
838      admin.disableTable(tableDescriptor.getTableName());
839      admin.truncateTable(tableDescriptor.getTableName(), true);
840      assertTrue(admin.isTableAvailable(tableDescriptor.getTableName()));
841      // delete table
842      admin.disableTable(tableDescriptor.getTableName());
843      admin.deleteTable(tableDescriptor.getTableName());
844      assertFalse(admin.tableExists(tableDescriptor.getTableName()));
845      // delete namespace
846      admin.deleteNamespace(namespace);
847      namespaceDescriptors = admin.listNamespaceDescriptors();
848      // should have 2 namespace, default and hbase
849      found = false;
850      for (NamespaceDescriptor nd : namespaceDescriptors) {
851        if (nd.getName().equals(namespace)) {
852          found = true;
853          break;
854        }
855      }
856      assertTrue(found == false);
857    }
858  }
859}