View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.client;
20  
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.assertNotNull;
23  
24  import org.apache.hadoop.hbase.SmallTests;
25  import org.junit.Test;
26  
27  import java.io.IOException;
28  import java.util.Arrays;
29  import java.util.HashMap;
30  import java.util.List;
31  import java.util.Map;
32  
33  import org.apache.hadoop.hbase.filter.BinaryComparator;
34  import org.apache.hadoop.hbase.filter.ColumnCountGetFilter;
35  import org.apache.hadoop.hbase.filter.ColumnPaginationFilter;
36  import org.apache.hadoop.hbase.filter.ColumnPrefixFilter;
37  import org.apache.hadoop.hbase.filter.ColumnRangeFilter;
38  import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
39  import org.apache.hadoop.hbase.filter.DependentColumnFilter;
40  import org.apache.hadoop.hbase.filter.FamilyFilter;
41  import org.apache.hadoop.hbase.filter.Filter;
42  import org.apache.hadoop.hbase.filter.FilterList;
43  import org.apache.hadoop.hbase.filter.FilterList.Operator;
44  import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
45  import org.apache.hadoop.hbase.filter.InclusiveStopFilter;
46  import org.apache.hadoop.hbase.filter.KeyOnlyFilter;
47  import org.apache.hadoop.hbase.filter.MultipleColumnPrefixFilter;
48  import org.apache.hadoop.hbase.filter.PageFilter;
49  import org.apache.hadoop.hbase.filter.PrefixFilter;
50  import org.apache.hadoop.hbase.filter.QualifierFilter;
51  import org.apache.hadoop.hbase.filter.RowFilter;
52  import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
53  import org.apache.hadoop.hbase.filter.SingleColumnValueExcludeFilter;
54  import org.apache.hadoop.hbase.filter.SkipFilter;
55  import org.apache.hadoop.hbase.filter.TimestampsFilter;
56  import org.apache.hadoop.hbase.filter.ValueFilter;
57  import org.apache.hadoop.hbase.filter.WhileMatchFilter;
58  import org.apache.hadoop.hbase.util.Bytes;
59  
60  import org.codehaus.jackson.map.ObjectMapper;
61  import org.junit.experimental.categories.Category;
62  
63  /**
64   * Run tests that use the functionality of the Operation superclass for
65   * Puts, Gets, Deletes, Scans, and MultiPuts.
66   */
67  @Category(SmallTests.class)
68  public class TestOperation {
69    private static byte [] ROW = Bytes.toBytes("testRow");
70    private static byte [] FAMILY = Bytes.toBytes("testFamily");
71    private static byte [] QUALIFIER = Bytes.toBytes("testQualifier");
72    private static byte [] VALUE = Bytes.toBytes("testValue");
73  
74    private static ObjectMapper mapper = new ObjectMapper();
75  
76    private static List<Long> TS_LIST = Arrays.asList(2L, 3L, 5L);
77    private static TimestampsFilter TS_FILTER = new TimestampsFilter(TS_LIST);
78    private static String STR_TS_FILTER =
79        TS_FILTER.getClass().getSimpleName() + " (3/3): [2, 3, 5]";
80  
81    private static List<Long> L_TS_LIST =
82        Arrays.asList(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L);
83    private static TimestampsFilter L_TS_FILTER =
84        new TimestampsFilter(L_TS_LIST);
85    private static String STR_L_TS_FILTER =
86        L_TS_FILTER.getClass().getSimpleName() + " (5/11): [0, 1, 2, 3, 4]";
87  
88    private static String COL_NAME_1 = "col1";
89    private static ColumnPrefixFilter COL_PRE_FILTER =
90        new ColumnPrefixFilter(COL_NAME_1.getBytes());
91    private static String STR_COL_PRE_FILTER =
92        COL_PRE_FILTER.getClass().getSimpleName() + " " + COL_NAME_1;
93  
94    private static String COL_NAME_2 = "col2";
95    private static ColumnRangeFilter CR_FILTER = new ColumnRangeFilter(
96        COL_NAME_1.getBytes(), true, COL_NAME_2.getBytes(), false);
97    private static String STR_CR_FILTER = CR_FILTER.getClass().getSimpleName()
98        + " [" + COL_NAME_1 + ", " + COL_NAME_2 + ")";
99  
100   private static int COL_COUNT = 9;
101   private static ColumnCountGetFilter CCG_FILTER =
102       new ColumnCountGetFilter(COL_COUNT);
103   private static String STR_CCG_FILTER =
104       CCG_FILTER.getClass().getSimpleName() + " " + COL_COUNT;
105 
106   private static int LIMIT = 3;
107   private static int OFFSET = 4;
108   private static ColumnPaginationFilter CP_FILTER =
109       new ColumnPaginationFilter(LIMIT, OFFSET);
110   private static String STR_CP_FILTER = CP_FILTER.getClass().getSimpleName()
111       + " (" + LIMIT + ", " + OFFSET + ")";
112 
113   private static String STOP_ROW_KEY = "stop";
114   private static InclusiveStopFilter IS_FILTER =
115       new InclusiveStopFilter(STOP_ROW_KEY.getBytes());
116   private static String STR_IS_FILTER =
117       IS_FILTER.getClass().getSimpleName() + " " + STOP_ROW_KEY;
118 
119   private static String PREFIX = "prefix";
120   private static PrefixFilter PREFIX_FILTER =
121       new PrefixFilter(PREFIX.getBytes());
122   private static String STR_PREFIX_FILTER = "PrefixFilter " + PREFIX;
123 
124   private static byte[][] PREFIXES = {
125       "0".getBytes(), "1".getBytes(), "2".getBytes()};
126   private static MultipleColumnPrefixFilter MCP_FILTER =
127       new MultipleColumnPrefixFilter(PREFIXES);
128   private static String STR_MCP_FILTER =
129       MCP_FILTER.getClass().getSimpleName() + " (3/3): [0, 1, 2]";
130 
131   private static byte[][] L_PREFIXES = {
132     "0".getBytes(), "1".getBytes(), "2".getBytes(), "3".getBytes(),
133     "4".getBytes(), "5".getBytes(), "6".getBytes(), "7".getBytes()};
134   private static MultipleColumnPrefixFilter L_MCP_FILTER =
135       new MultipleColumnPrefixFilter(L_PREFIXES);
136   private static String STR_L_MCP_FILTER =
137       L_MCP_FILTER.getClass().getSimpleName() + " (5/8): [0, 1, 2, 3, 4]";
138 
139   private static int PAGE_SIZE = 9;
140   private static PageFilter PAGE_FILTER = new PageFilter(PAGE_SIZE);
141   private static String STR_PAGE_FILTER =
142       PAGE_FILTER.getClass().getSimpleName() + " " + PAGE_SIZE;
143 
144   private static SkipFilter SKIP_FILTER = new SkipFilter(L_TS_FILTER);
145   private static String STR_SKIP_FILTER =
146       SKIP_FILTER.getClass().getSimpleName() + " " + STR_L_TS_FILTER;
147 
148   private static WhileMatchFilter WHILE_FILTER =
149       new WhileMatchFilter(L_TS_FILTER);
150   private static String STR_WHILE_FILTER =
151       WHILE_FILTER.getClass().getSimpleName() + " " + STR_L_TS_FILTER;
152 
153   private static KeyOnlyFilter KEY_ONLY_FILTER = new KeyOnlyFilter();
154   private static String STR_KEY_ONLY_FILTER =
155       KEY_ONLY_FILTER.getClass().getSimpleName();
156 
157   private static FirstKeyOnlyFilter FIRST_KEY_ONLY_FILTER =
158       new FirstKeyOnlyFilter();
159   private static String STR_FIRST_KEY_ONLY_FILTER =
160       FIRST_KEY_ONLY_FILTER.getClass().getSimpleName();
161 
162   private static CompareOp CMP_OP = CompareOp.EQUAL;
163   private static byte[] CMP_VALUE = "value".getBytes();
164   private static BinaryComparator BC = new BinaryComparator(CMP_VALUE);
165   private static DependentColumnFilter DC_FILTER =
166       new DependentColumnFilter(FAMILY, QUALIFIER, true, CMP_OP, BC);
167   private static String STR_DC_FILTER = String.format(
168       "%s (%s, %s, %s, %s, %s)", DC_FILTER.getClass().getSimpleName(),
169       Bytes.toStringBinary(FAMILY), Bytes.toStringBinary(QUALIFIER), true,
170       CMP_OP.name(), Bytes.toStringBinary(BC.getValue()));
171 
172   private static FamilyFilter FAMILY_FILTER = new FamilyFilter(CMP_OP, BC);
173   private static String STR_FAMILY_FILTER =
174       FAMILY_FILTER.getClass().getSimpleName() + " (EQUAL, value)";
175 
176   private static QualifierFilter QUALIFIER_FILTER =
177       new QualifierFilter(CMP_OP, BC);
178   private static String STR_QUALIFIER_FILTER =
179       QUALIFIER_FILTER.getClass().getSimpleName() + " (EQUAL, value)";
180 
181   private static RowFilter ROW_FILTER = new RowFilter(CMP_OP, BC);
182   private static String STR_ROW_FILTER =
183       ROW_FILTER.getClass().getSimpleName() + " (EQUAL, value)";
184 
185   private static ValueFilter VALUE_FILTER = new ValueFilter(CMP_OP, BC);
186   private static String STR_VALUE_FILTER =
187       VALUE_FILTER.getClass().getSimpleName() + " (EQUAL, value)";
188 
189   private static SingleColumnValueFilter SCV_FILTER =
190       new SingleColumnValueFilter(FAMILY, QUALIFIER, CMP_OP, CMP_VALUE);
191   private static String STR_SCV_FILTER = String.format("%s (%s, %s, %s, %s)",
192       SCV_FILTER.getClass().getSimpleName(), Bytes.toStringBinary(FAMILY),
193       Bytes.toStringBinary(QUALIFIER), CMP_OP.name(),
194       Bytes.toStringBinary(CMP_VALUE));
195 
196   private static SingleColumnValueExcludeFilter SCVE_FILTER =
197       new SingleColumnValueExcludeFilter(FAMILY, QUALIFIER, CMP_OP, CMP_VALUE);
198   private static String STR_SCVE_FILTER = String.format("%s (%s, %s, %s, %s)",
199       SCVE_FILTER.getClass().getSimpleName(), Bytes.toStringBinary(FAMILY),
200       Bytes.toStringBinary(QUALIFIER), CMP_OP.name(),
201       Bytes.toStringBinary(CMP_VALUE));
202 
203   private static FilterList AND_FILTER_LIST = new FilterList(
204       Operator.MUST_PASS_ALL, Arrays.asList((Filter) TS_FILTER, L_TS_FILTER,
205           CR_FILTER));
206   private static String STR_AND_FILTER_LIST = String.format(
207       "%s AND (3/3): [%s, %s, %s]", AND_FILTER_LIST.getClass().getSimpleName(),
208       STR_TS_FILTER, STR_L_TS_FILTER, STR_CR_FILTER);
209 
210   private static FilterList OR_FILTER_LIST = new FilterList(
211       Operator.MUST_PASS_ONE, Arrays.asList((Filter) TS_FILTER, L_TS_FILTER,
212           CR_FILTER));
213   private static String STR_OR_FILTER_LIST = String.format(
214       "%s OR (3/3): [%s, %s, %s]", AND_FILTER_LIST.getClass().getSimpleName(),
215       STR_TS_FILTER, STR_L_TS_FILTER, STR_CR_FILTER);
216 
217   private static FilterList L_FILTER_LIST = new FilterList(
218       Arrays.asList((Filter) TS_FILTER, L_TS_FILTER, CR_FILTER, COL_PRE_FILTER,
219           CCG_FILTER, CP_FILTER, PREFIX_FILTER, PAGE_FILTER));
220   private static String STR_L_FILTER_LIST = String.format(
221       "%s AND (5/8): [%s, %s, %s, %s, %s]",
222       L_FILTER_LIST.getClass().getSimpleName(), STR_TS_FILTER, STR_L_TS_FILTER,
223       STR_CR_FILTER, STR_COL_PRE_FILTER, STR_CCG_FILTER, STR_CP_FILTER);
224 
225   private static Filter[] FILTERS = {
226     TS_FILTER,             // TimestampsFilter
227     L_TS_FILTER,           // TimestampsFilter
228     COL_PRE_FILTER,        // ColumnPrefixFilter
229     CP_FILTER,             // ColumnPaginationFilter
230     CR_FILTER,             // ColumnRangeFilter
231     CCG_FILTER,            // ColumnCountGetFilter
232     IS_FILTER,             // InclusiveStopFilter
233     PREFIX_FILTER,         // PrefixFilter
234     PAGE_FILTER,           // PageFilter
235     SKIP_FILTER,           // SkipFilter
236     WHILE_FILTER,          // WhileMatchFilter
237     KEY_ONLY_FILTER,       // KeyOnlyFilter
238     FIRST_KEY_ONLY_FILTER, // FirstKeyOnlyFilter
239     MCP_FILTER,            // MultipleColumnPrefixFilter
240     L_MCP_FILTER,          // MultipleColumnPrefixFilter
241     DC_FILTER,             // DependentColumnFilter
242     FAMILY_FILTER,         // FamilyFilter
243     QUALIFIER_FILTER,      // QualifierFilter
244     ROW_FILTER,            // RowFilter
245     VALUE_FILTER,          // ValueFilter
246     SCV_FILTER,            // SingleColumnValueFilter
247     SCVE_FILTER,           // SingleColumnValueExcludeFilter
248     AND_FILTER_LIST,       // FilterList
249     OR_FILTER_LIST,        // FilterList
250     L_FILTER_LIST,         // FilterList
251   };
252 
253   private static String[] FILTERS_INFO = {
254     STR_TS_FILTER,             // TimestampsFilter
255     STR_L_TS_FILTER,           // TimestampsFilter
256     STR_COL_PRE_FILTER,        // ColumnPrefixFilter
257     STR_CP_FILTER,             // ColumnPaginationFilter
258     STR_CR_FILTER,             // ColumnRangeFilter
259     STR_CCG_FILTER,            // ColumnCountGetFilter
260     STR_IS_FILTER,             // InclusiveStopFilter
261     STR_PREFIX_FILTER,         // PrefixFilter
262     STR_PAGE_FILTER,           // PageFilter
263     STR_SKIP_FILTER,           // SkipFilter
264     STR_WHILE_FILTER,          // WhileMatchFilter
265     STR_KEY_ONLY_FILTER,       // KeyOnlyFilter
266     STR_FIRST_KEY_ONLY_FILTER, // FirstKeyOnlyFilter
267     STR_MCP_FILTER,            // MultipleColumnPrefixFilter
268     STR_L_MCP_FILTER,          // MultipleColumnPrefixFilter
269     STR_DC_FILTER,             // DependentColumnFilter
270     STR_FAMILY_FILTER,         // FamilyFilter
271     STR_QUALIFIER_FILTER,      // QualifierFilter
272     STR_ROW_FILTER,            // RowFilter
273     STR_VALUE_FILTER,          // ValueFilter
274     STR_SCV_FILTER,            // SingleColumnValueFilter
275     STR_SCVE_FILTER,           // SingleColumnValueExcludeFilter
276     STR_AND_FILTER_LIST,       // FilterList
277     STR_OR_FILTER_LIST,        // FilterList
278     STR_L_FILTER_LIST,         // FilterList
279   };
280 
281   static {
282     assertEquals("The sizes of static arrays do not match: "
283         + "[FILTERS: %d <=> FILTERS_INFO: %d]",
284         FILTERS.length, FILTERS_INFO.length);
285   }
286 
287   /**
288    * Test the client Operations' JSON encoding to ensure that produced JSON is 
289    * parseable and that the details are present and not corrupted.
290    * @throws IOException
291    */
292   @Test
293   public void testOperationJSON()
294       throws IOException {
295     // produce a Scan Operation
296     Scan scan = new Scan(ROW);
297     scan.addColumn(FAMILY, QUALIFIER);
298     // get its JSON representation, and parse it
299     String json = scan.toJSON();
300     Map<String, Object> parsedJSON = mapper.readValue(json, HashMap.class);
301     // check for the row
302     assertEquals("startRow incorrect in Scan.toJSON()",
303         Bytes.toStringBinary(ROW), parsedJSON.get("startRow"));
304     // check for the family and the qualifier.
305     List familyInfo = (List) ((Map) parsedJSON.get("families")).get(
306         Bytes.toStringBinary(FAMILY));
307     assertNotNull("Family absent in Scan.toJSON()", familyInfo);
308     assertEquals("Qualifier absent in Scan.toJSON()", 1, familyInfo.size());
309     assertEquals("Qualifier incorrect in Scan.toJSON()",
310         Bytes.toStringBinary(QUALIFIER),
311         familyInfo.get(0));
312 
313     // produce a Get Operation
314     Get get = new Get(ROW);
315     get.addColumn(FAMILY, QUALIFIER);
316     // get its JSON representation, and parse it
317     json = get.toJSON();
318     parsedJSON = mapper.readValue(json, HashMap.class);
319     // check for the row
320     assertEquals("row incorrect in Get.toJSON()",
321         Bytes.toStringBinary(ROW), parsedJSON.get("row"));
322     // check for the family and the qualifier.
323     familyInfo = (List) ((Map) parsedJSON.get("families")).get(
324         Bytes.toStringBinary(FAMILY));
325     assertNotNull("Family absent in Get.toJSON()", familyInfo);
326     assertEquals("Qualifier absent in Get.toJSON()", 1, familyInfo.size());
327     assertEquals("Qualifier incorrect in Get.toJSON()",
328         Bytes.toStringBinary(QUALIFIER),
329         familyInfo.get(0));
330 
331     // produce a Put operation
332     Put put = new Put(ROW);
333     put.add(FAMILY, QUALIFIER, VALUE);
334     // get its JSON representation, and parse it
335     json = put.toJSON();
336     parsedJSON = mapper.readValue(json, HashMap.class);
337     // check for the row
338     assertEquals("row absent in Put.toJSON()",
339         Bytes.toStringBinary(ROW), parsedJSON.get("row"));
340     // check for the family and the qualifier.
341     familyInfo = (List) ((Map) parsedJSON.get("families")).get(
342         Bytes.toStringBinary(FAMILY));
343     assertNotNull("Family absent in Put.toJSON()", familyInfo);
344     assertEquals("KeyValue absent in Put.toJSON()", 1, familyInfo.size());
345     Map kvMap = (Map) familyInfo.get(0);
346     assertEquals("Qualifier incorrect in Put.toJSON()",
347         Bytes.toStringBinary(QUALIFIER),
348         kvMap.get("qualifier"));
349     assertEquals("Value length incorrect in Put.toJSON()", 
350         VALUE.length, kvMap.get("vlen"));
351 
352     // produce a Delete operation
353     Delete delete = new Delete(ROW);
354     delete.deleteColumn(FAMILY, QUALIFIER);
355     // get its JSON representation, and parse it
356     json = delete.toJSON();
357     parsedJSON = mapper.readValue(json, HashMap.class);
358     // check for the row
359     assertEquals("row absent in Delete.toJSON()",
360         Bytes.toStringBinary(ROW), parsedJSON.get("row"));
361     // check for the family and the qualifier.
362     familyInfo = (List) ((Map) parsedJSON.get("families")).get(
363         Bytes.toStringBinary(FAMILY));
364     assertNotNull("Family absent in Delete.toJSON()", familyInfo);
365     assertEquals("KeyValue absent in Delete.toJSON()", 1, familyInfo.size());
366     kvMap = (Map) familyInfo.get(0);
367     assertEquals("Qualifier incorrect in Delete.toJSON()", 
368         Bytes.toStringBinary(QUALIFIER), kvMap.get("qualifier"));
369   }
370 
371 }
372