1   /*
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase.rest.client;
22  
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.assertNotNull;
25  import static org.junit.Assert.assertNull;
26  import static org.junit.Assert.assertTrue;
27  import static org.junit.Assert.assertFalse;
28  
29  import java.io.IOException;
30  import java.util.ArrayList;
31  import java.util.Collections;
32  import java.util.Iterator;
33  import java.util.List;
34  
35  import org.apache.commons.httpclient.Header;
36  import org.apache.hadoop.hbase.HBaseTestingUtility;
37  import org.apache.hadoop.hbase.HColumnDescriptor;
38  import org.apache.hadoop.hbase.HTableDescriptor;
39  import org.apache.hadoop.hbase.KeyValue;
40  import org.apache.hadoop.hbase.MediumTests;
41  import org.apache.hadoop.hbase.client.Delete;
42  import org.apache.hadoop.hbase.client.Get;
43  import org.apache.hadoop.hbase.client.HBaseAdmin;
44  import org.apache.hadoop.hbase.client.HTable;
45  import org.apache.hadoop.hbase.client.Put;
46  import org.apache.hadoop.hbase.client.Result;
47  import org.apache.hadoop.hbase.client.ResultScanner;
48  import org.apache.hadoop.hbase.client.Scan;
49  import org.apache.hadoop.hbase.rest.HBaseRESTTestingUtility;
50  import org.apache.hadoop.hbase.util.Bytes;
51  import org.junit.After;
52  import org.junit.AfterClass;
53  import org.junit.Before;
54  import org.junit.BeforeClass;
55  import org.junit.Test;
56  import org.junit.experimental.categories.Category;
57  
58  @Category(MediumTests.class)
59  public class TestRemoteTable {
60    private static final String TABLE = "TestRemoteTable";
61    private static final byte[] ROW_1 = Bytes.toBytes("testrow1");
62    private static final byte[] ROW_2 = Bytes.toBytes("testrow2");
63    private static final byte[] ROW_3 = Bytes.toBytes("testrow3");
64    private static final byte[] ROW_4 = Bytes.toBytes("testrow4");
65    private static final byte[] COLUMN_1 = Bytes.toBytes("a");
66    private static final byte[] COLUMN_2 = Bytes.toBytes("b");
67    private static final byte[] COLUMN_3 = Bytes.toBytes("c");
68    private static final byte[] QUALIFIER_1 = Bytes.toBytes("1");
69    private static final byte[] QUALIFIER_2 = Bytes.toBytes("2");
70    private static final byte[] VALUE_1 = Bytes.toBytes("testvalue1");
71    private static final byte[] VALUE_2 = Bytes.toBytes("testvalue2");
72  
73    private static final long ONE_HOUR = 60 * 60 * 1000;
74    private static final long TS_2 = System.currentTimeMillis();
75    private static final long TS_1 = TS_2 - ONE_HOUR;
76  
77    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
78    private static final HBaseRESTTestingUtility REST_TEST_UTIL = 
79      new HBaseRESTTestingUtility();
80    private RemoteHTable remoteTable;
81  
82    @BeforeClass
83    public static void setUpBeforeClass() throws Exception {
84      TEST_UTIL.startMiniCluster();
85      REST_TEST_UTIL.startServletContainer(TEST_UTIL.getConfiguration());
86    }
87  
88    @Before
89    public void before() throws Exception  {
90      HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
91      if (admin.tableExists(TABLE)) {
92        if (admin.isTableEnabled(TABLE)) admin.disableTable(TABLE);
93        admin.deleteTable(TABLE);
94      }
95      HTableDescriptor htd = new HTableDescriptor(TABLE);
96      htd.addFamily(new HColumnDescriptor(COLUMN_1).setMaxVersions(3));
97      htd.addFamily(new HColumnDescriptor(COLUMN_2).setMaxVersions(3));
98      htd.addFamily(new HColumnDescriptor(COLUMN_3).setMaxVersions(3));
99      admin.createTable(htd);
100     HTable table = null;
101     try {
102       table = new HTable(TEST_UTIL.getConfiguration(), TABLE);
103       Put put = new Put(ROW_1);
104       put.add(COLUMN_1, QUALIFIER_1, TS_2, VALUE_1);
105       table.put(put);
106       put = new Put(ROW_2);
107       put.add(COLUMN_1, QUALIFIER_1, TS_1, VALUE_1);
108       put.add(COLUMN_1, QUALIFIER_1, TS_2, VALUE_2);
109       put.add(COLUMN_2, QUALIFIER_2, TS_2, VALUE_2);
110       table.put(put);
111       table.flushCommits();
112     } finally {
113       if (null != table) table.close();
114     }
115     remoteTable = new RemoteHTable(
116       new Client(new Cluster().add("localhost", 
117           REST_TEST_UTIL.getServletPort())),
118         TEST_UTIL.getConfiguration(), TABLE);
119   }
120   
121   @After
122   public void after() throws Exception {
123     remoteTable.close();
124   }
125   
126   @AfterClass
127   public static void tearDownAfterClass() throws Exception {
128     REST_TEST_UTIL.shutdownServletContainer();
129     TEST_UTIL.shutdownMiniCluster();
130   }
131 
132   @Test
133   public void testGetTableDescriptor() throws IOException {
134     HTable table = null;
135     try {
136       table = new HTable(TEST_UTIL.getConfiguration(), TABLE);
137       HTableDescriptor local = table.getTableDescriptor();
138       assertEquals(remoteTable.getTableDescriptor(), local);
139     } finally {
140       if (null != table) table.close();
141     }
142   }
143 
144   @Test
145   public void testGet() throws IOException {
146     Get get = new Get(ROW_1);
147     Result result = remoteTable.get(get);
148     byte[] value1 = result.getValue(COLUMN_1, QUALIFIER_1);
149     byte[] value2 = result.getValue(COLUMN_2, QUALIFIER_2);
150     assertNotNull(value1);
151     assertTrue(Bytes.equals(VALUE_1, value1));
152     assertNull(value2);
153 
154     get = new Get(ROW_1);
155     get.addFamily(COLUMN_3);
156     result = remoteTable.get(get);
157     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
158     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
159     assertNull(value1);
160     assertNull(value2);
161 
162     get = new Get(ROW_1);
163     get.addColumn(COLUMN_1, QUALIFIER_1);
164     get.addColumn(COLUMN_2, QUALIFIER_2);
165     result = remoteTable.get(get);
166     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
167     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
168     assertNotNull(value1);
169     assertTrue(Bytes.equals(VALUE_1, value1));
170     assertNull(value2);
171 
172     get = new Get(ROW_2);
173     result = remoteTable.get(get);    
174     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
175     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
176     assertNotNull(value1);
177     assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
178     assertNotNull(value2);
179     assertTrue(Bytes.equals(VALUE_2, value2));
180 
181     get = new Get(ROW_2);
182     get.addFamily(COLUMN_1);
183     result = remoteTable.get(get);    
184     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
185     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
186     assertNotNull(value1);
187     assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
188     assertNull(value2);
189 
190     get = new Get(ROW_2);
191     get.addColumn(COLUMN_1, QUALIFIER_1);
192     get.addColumn(COLUMN_2, QUALIFIER_2);
193     result = remoteTable.get(get);    
194     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
195     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
196     assertNotNull(value1);
197     assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
198     assertNotNull(value2);
199     assertTrue(Bytes.equals(VALUE_2, value2));
200 
201     // test timestamp
202 
203     get = new Get(ROW_2);
204     get.addFamily(COLUMN_1);
205     get.addFamily(COLUMN_2);
206     get.setTimeStamp(TS_1);
207     result = remoteTable.get(get);    
208     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
209     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
210     assertNotNull(value1);
211     assertTrue(Bytes.equals(VALUE_1, value1)); // @TS_1
212     assertNull(value2);
213 
214     // test timerange
215 
216     get = new Get(ROW_2);
217     get.addFamily(COLUMN_1);
218     get.addFamily(COLUMN_2);
219     get.setTimeRange(0, TS_1 + 1);
220     result = remoteTable.get(get);    
221     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
222     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
223     assertNotNull(value1);
224     assertTrue(Bytes.equals(VALUE_1, value1)); // @TS_1
225     assertNull(value2);
226 
227     // test maxVersions
228 
229     get = new Get(ROW_2);
230     get.addFamily(COLUMN_1);
231     get.setMaxVersions(2);
232     result = remoteTable.get(get);
233     int count = 0;
234     for (KeyValue kv: result.list()) {
235       if (Bytes.equals(COLUMN_1, kv.getFamily()) && TS_1 == kv.getTimestamp()) {
236         assertTrue(Bytes.equals(VALUE_1, kv.getValue())); // @TS_1
237         count++;
238       }
239       if (Bytes.equals(COLUMN_1, kv.getFamily()) && TS_2 == kv.getTimestamp()) {
240         assertTrue(Bytes.equals(VALUE_2, kv.getValue())); // @TS_2
241         count++;
242       }
243     }
244     assertEquals(2, count);
245   }
246 
247   @Test
248   public void testMultiGet() throws Exception {
249     ArrayList<Get> gets = new ArrayList<Get>();
250     gets.add(new Get(ROW_1));
251     gets.add(new Get(ROW_2));
252     Result[] results = remoteTable.get(gets);
253     assertNotNull(results);
254     assertEquals(2, results.length);
255     assertEquals(1, results[0].size());
256     assertEquals(2, results[1].size());
257 
258     //Test Versions
259     gets = new ArrayList<Get>();
260     Get g = new Get(ROW_1);
261     g.setMaxVersions(3);
262     gets.add(g);
263     gets.add(new Get(ROW_2));
264     results = remoteTable.get(gets);
265     assertNotNull(results);
266     assertEquals(2, results.length);
267     assertEquals(1, results[0].size());
268     assertEquals(3, results[1].size());
269 
270     //404
271     gets = new ArrayList<Get>();
272     gets.add(new Get(Bytes.toBytes("RESALLYREALLYNOTTHERE")));
273     results = remoteTable.get(gets);
274     assertNotNull(results);
275     assertEquals(0, results.length);
276 
277     gets = new ArrayList<Get>();
278     gets.add(new Get(Bytes.toBytes("RESALLYREALLYNOTTHERE")));
279     gets.add(new Get(ROW_1));
280     gets.add(new Get(ROW_2));
281     results = remoteTable.get(gets);
282     assertNotNull(results);
283     assertEquals(0, results.length);
284   }
285 
286   @Test
287   public void testPut() throws IOException {
288     Put put = new Put(ROW_3);
289     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
290     remoteTable.put(put);
291 
292     Get get = new Get(ROW_3);
293     get.addFamily(COLUMN_1);
294     Result result = remoteTable.get(get);
295     byte[] value = result.getValue(COLUMN_1, QUALIFIER_1);
296     assertNotNull(value);
297     assertTrue(Bytes.equals(VALUE_1, value));
298 
299     // multiput
300 
301     List<Put> puts = new ArrayList<Put>();
302     put = new Put(ROW_3);
303     put.add(COLUMN_2, QUALIFIER_2, VALUE_2);
304     puts.add(put);
305     put = new Put(ROW_4);
306     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
307     puts.add(put);
308     put = new Put(ROW_4);
309     put.add(COLUMN_2, QUALIFIER_2, VALUE_2);
310     puts.add(put);
311     remoteTable.put(puts);
312 
313     get = new Get(ROW_3);
314     get.addFamily(COLUMN_2);
315     result = remoteTable.get(get);
316     value = result.getValue(COLUMN_2, QUALIFIER_2);
317     assertNotNull(value);
318     assertTrue(Bytes.equals(VALUE_2, value));
319     get = new Get(ROW_4);
320     result = remoteTable.get(get);
321     value = result.getValue(COLUMN_1, QUALIFIER_1);
322     assertNotNull(value);
323     assertTrue(Bytes.equals(VALUE_1, value));
324     value = result.getValue(COLUMN_2, QUALIFIER_2);
325     assertNotNull(value);
326     assertTrue(Bytes.equals(VALUE_2, value));
327 
328     assertTrue(Bytes.equals(Bytes.toBytes("TestRemoteTable"), remoteTable.getTableName()));
329   }
330 
331   @Test
332   public void testDelete() throws IOException {
333     Put put = new Put(ROW_3);
334     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
335     put.add(COLUMN_2, QUALIFIER_2, VALUE_2);
336     remoteTable.put(put);
337 
338     Get get = new Get(ROW_3);
339     get.addFamily(COLUMN_1);
340     get.addFamily(COLUMN_2);
341     Result result = remoteTable.get(get);
342     byte[] value1 = result.getValue(COLUMN_1, QUALIFIER_1);
343     byte[] value2 = result.getValue(COLUMN_2, QUALIFIER_2);
344     assertNotNull(value1);
345     assertTrue(Bytes.equals(VALUE_1, value1));
346     assertNotNull(value2);
347     assertTrue(Bytes.equals(VALUE_2, value2));
348 
349     Delete delete = new Delete(ROW_3);
350     delete.deleteColumn(COLUMN_2, QUALIFIER_2);
351     remoteTable.delete(delete);
352 
353     get = new Get(ROW_3);
354     get.addFamily(COLUMN_1);
355     get.addFamily(COLUMN_2);
356     result = remoteTable.get(get);
357     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
358     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
359     assertNotNull(value1);
360     assertTrue(Bytes.equals(VALUE_1, value1));
361     assertNull(value2);
362 
363     delete = new Delete(ROW_3);
364     delete.setTimestamp(1L);
365     remoteTable.delete(delete);
366 
367     get = new Get(ROW_3);
368     get.addFamily(COLUMN_1);
369     get.addFamily(COLUMN_2);
370     result = remoteTable.get(get);
371     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
372     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
373     assertNotNull(value1);
374     assertTrue(Bytes.equals(VALUE_1, value1));
375     assertNull(value2);
376 
377     delete = new Delete(ROW_3);
378     remoteTable.delete(delete);
379 
380     get = new Get(ROW_3);
381     get.addFamily(COLUMN_1);
382     get.addFamily(COLUMN_2);
383     result = remoteTable.get(get);
384     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
385     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
386     assertNull(value1);
387     assertNull(value2);
388   }
389 
390   @Test
391   public void testScanner() throws IOException {
392     List<Put> puts = new ArrayList<Put>();
393     Put put = new Put(ROW_1);
394     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
395     puts.add(put);
396     put = new Put(ROW_2);
397     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
398     puts.add(put);
399     put = new Put(ROW_3);
400     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
401     puts.add(put);
402     put = new Put(ROW_4);
403     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
404     puts.add(put);
405     remoteTable.put(puts);
406 
407     ResultScanner scanner = remoteTable.getScanner(new Scan());
408 
409     Result[] results = scanner.next(1);
410     assertNotNull(results);
411     assertEquals(1, results.length);
412     assertTrue(Bytes.equals(ROW_1, results[0].getRow()));
413 
414     Result result = scanner.next();
415     assertNotNull(result);
416     assertTrue(Bytes.equals(ROW_2, result.getRow()));
417 
418     results = scanner.next(2);
419     assertNotNull(results);
420     assertEquals(2, results.length);
421     assertTrue(Bytes.equals(ROW_3, results[0].getRow()));
422     assertTrue(Bytes.equals(ROW_4, results[1].getRow()));
423 
424     results = scanner.next(1);
425     assertNull(results);
426     scanner.close();
427 
428     scanner = remoteTable.getScanner(COLUMN_1);
429     results = scanner.next(4);
430     assertNotNull(results);
431     assertEquals(4, results.length);
432     assertTrue(Bytes.equals(ROW_1, results[0].getRow()));
433     assertTrue(Bytes.equals(ROW_2, results[1].getRow()));
434     assertTrue(Bytes.equals(ROW_3, results[2].getRow()));
435     assertTrue(Bytes.equals(ROW_4, results[3].getRow()));
436 
437     scanner.close();
438 
439     scanner = remoteTable.getScanner(COLUMN_1, QUALIFIER_1);
440     results = scanner.next(4);
441     assertNotNull(results);
442     assertEquals(4, results.length);
443     assertTrue(Bytes.equals(ROW_1, results[0].getRow()));
444     assertTrue(Bytes.equals(ROW_2, results[1].getRow()));
445     assertTrue(Bytes.equals(ROW_3, results[2].getRow()));
446     assertTrue(Bytes.equals(ROW_4, results[3].getRow()));
447     scanner.close();
448     assertTrue(remoteTable.isAutoFlush());
449   }
450 
451   @Test
452   public void testCheckAndDelete() throws IOException {
453     Get get = new Get(ROW_1);
454     Result result = remoteTable.get(get);
455     byte[] value1 = result.getValue(COLUMN_1, QUALIFIER_1);
456     byte[] value2 = result.getValue(COLUMN_2, QUALIFIER_2);
457     assertNotNull(value1);
458     assertTrue(Bytes.equals(VALUE_1, value1));
459     assertNull(value2);
460     assertTrue(remoteTable.exists(get));
461     assertEquals(1, remoteTable.get(Collections.singletonList(get)).length);
462     Delete delete = new Delete(ROW_1);
463 
464     remoteTable.checkAndDelete(ROW_1, COLUMN_1, QUALIFIER_1, VALUE_1, delete);
465     assertFalse(remoteTable.exists(get));
466 
467     Put put = new Put(ROW_1);
468     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
469     remoteTable.put(put);
470 
471     assertTrue(remoteTable.checkAndPut(ROW_1, COLUMN_1, QUALIFIER_1, VALUE_1, put));
472     assertFalse(remoteTable.checkAndPut(ROW_1, COLUMN_1, QUALIFIER_1, VALUE_2, put));
473   }
474 
475   /**
476    * Test RemoteHable.Scanner.iterator method  
477    */
478   @Test
479   public void testIteratorScaner() throws IOException {
480     List<Put> puts = new ArrayList<Put>();
481     Put put = new Put(ROW_1);
482     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
483     puts.add(put);
484     put = new Put(ROW_2);
485     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
486     puts.add(put);
487     put = new Put(ROW_3);
488     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
489     puts.add(put);
490     put = new Put(ROW_4);
491     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
492     puts.add(put);
493     remoteTable.put(puts);
494 
495     ResultScanner scanner = remoteTable.getScanner(new Scan());
496     Iterator<Result> iterator = scanner.iterator();
497     assertTrue(iterator.hasNext());
498     int counter = 0;
499     while (iterator.hasNext()) {
500       iterator.next();
501       counter++;
502     }
503     assertEquals(4, counter);
504   }
505 
506   /**
507    * Test a some methods of class Response.
508    */
509   @Test
510   public void testResponse(){
511     Response response = new Response(200);
512     assertEquals(200, response.getCode());
513     Header[] headers = new Header[2];
514     headers[0] = new Header("header1", "value1");
515     headers[1] = new Header("header2", "value2");
516     response = new Response(200, headers);
517     assertEquals("value1", response.getHeader("header1"));
518     assertFalse(response.hasBody());
519     response.setCode(404);
520     assertEquals(404, response.getCode());
521     headers = new Header[2];
522     headers[0] = new Header("header1", "value1.1");
523     headers[1] = new Header("header2", "value2");
524     response.setHeaders(headers);
525     assertEquals("value1.1", response.getHeader("header1"));
526     response.setBody(Bytes.toBytes("body"));
527     assertTrue(response.hasBody());    
528   }
529 
530   @org.junit.Rule
531   public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu =
532     new org.apache.hadoop.hbase.ResourceCheckerJUnitRule();
533 }