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.filter;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertFalse;
022import static org.junit.Assert.assertTrue;
023import java.io.IOException;
024import java.nio.charset.StandardCharsets;
025import java.util.ArrayList;
026import java.util.List;
027import java.util.regex.Pattern;
028import org.apache.hadoop.hbase.CompareOperator;
029import org.apache.hadoop.hbase.HBaseClassTestRule;
030import org.apache.hadoop.hbase.testclassification.MediumTests;
031import org.apache.hadoop.hbase.testclassification.RegionServerTests;
032import org.apache.hadoop.hbase.util.Bytes;
033import org.junit.After;
034import org.junit.Before;
035import org.junit.ClassRule;
036import org.junit.Test;
037import org.junit.experimental.categories.Category;
038
039/**
040 * This class tests ParseFilter.java
041 * It tests the entire work flow from when a string is given by the user
042 * and how it is parsed to construct the corresponding Filter object
043 */
044@Category({RegionServerTests.class, MediumTests.class})
045public class TestParseFilter {
046
047  @ClassRule
048  public static final HBaseClassTestRule CLASS_RULE =
049      HBaseClassTestRule.forClass(TestParseFilter.class);
050
051  ParseFilter f;
052  Filter filter;
053
054  @Before
055  public void setUp() throws Exception {
056    f = new ParseFilter();
057  }
058
059  @After
060  public void tearDown() throws Exception {
061    // Nothing to do.
062  }
063
064  @Test
065  public void testKeyOnlyFilter() throws IOException {
066    String filterString = "KeyOnlyFilter()";
067    doTestFilter(filterString, KeyOnlyFilter.class);
068
069    String filterString2 = "KeyOnlyFilter ('') ";
070    byte [] filterStringAsByteArray2 = Bytes.toBytes(filterString2);
071    try {
072      filter = f.parseFilterString(filterStringAsByteArray2);
073      assertTrue(false);
074    } catch (IllegalArgumentException e) {
075      System.out.println(e.getMessage());
076    }
077  }
078
079  @Test
080  public void testFirstKeyOnlyFilter() throws IOException {
081    String filterString = " FirstKeyOnlyFilter( ) ";
082    doTestFilter(filterString, FirstKeyOnlyFilter.class);
083
084    String filterString2 = " FirstKeyOnlyFilter ('') ";
085    byte [] filterStringAsByteArray2 = Bytes.toBytes(filterString2);
086    try {
087      filter = f.parseFilterString(filterStringAsByteArray2);
088      assertTrue(false);
089    } catch (IllegalArgumentException e) {
090      System.out.println(e.getMessage());
091    }
092  }
093
094  @Test
095  public void testPrefixFilter() throws IOException {
096    String filterString = " PrefixFilter('row' ) ";
097    PrefixFilter prefixFilter = doTestFilter(filterString, PrefixFilter.class);
098    byte [] prefix = prefixFilter.getPrefix();
099    assertEquals("row", new String(prefix, StandardCharsets.UTF_8));
100
101
102    filterString = " PrefixFilter(row)";
103    try {
104      doTestFilter(filterString, PrefixFilter.class);
105      assertTrue(false);
106    } catch (IllegalArgumentException e) {
107      System.out.println(e.getMessage());
108    }
109  }
110
111  @Test
112  public void testColumnPrefixFilter() throws IOException {
113    String filterString = " ColumnPrefixFilter('qualifier' ) ";
114    ColumnPrefixFilter columnPrefixFilter =
115      doTestFilter(filterString, ColumnPrefixFilter.class);
116    byte [] columnPrefix = columnPrefixFilter.getPrefix();
117    assertEquals("qualifier", new String(columnPrefix, StandardCharsets.UTF_8));
118  }
119
120  @Test
121  public void testMultipleColumnPrefixFilter() throws IOException {
122    String filterString = " MultipleColumnPrefixFilter('qualifier1', 'qualifier2' ) ";
123    MultipleColumnPrefixFilter multipleColumnPrefixFilter =
124      doTestFilter(filterString, MultipleColumnPrefixFilter.class);
125    byte [][] prefixes = multipleColumnPrefixFilter.getPrefix();
126    assertEquals("qualifier1", new String(prefixes[0], StandardCharsets.UTF_8));
127    assertEquals("qualifier2", new String(prefixes[1], StandardCharsets.UTF_8));
128  }
129
130  @Test
131  public void testColumnCountGetFilter() throws IOException {
132    String filterString = " ColumnCountGetFilter(4)";
133    ColumnCountGetFilter columnCountGetFilter =
134      doTestFilter(filterString, ColumnCountGetFilter.class);
135    int limit = columnCountGetFilter.getLimit();
136    assertEquals(4, limit);
137
138    filterString = " ColumnCountGetFilter('abc')";
139    try {
140      doTestFilter(filterString, ColumnCountGetFilter.class);
141      assertTrue(false);
142    } catch (IllegalArgumentException e) {
143      System.out.println(e.getMessage());
144    }
145
146    filterString = " ColumnCountGetFilter(2147483648)";
147    try {
148      doTestFilter(filterString, ColumnCountGetFilter.class);
149      assertTrue(false);
150    } catch (IllegalArgumentException e) {
151      System.out.println(e.getMessage());
152    }
153  }
154
155  @Test
156  public void testPageFilter() throws IOException {
157    String filterString = " PageFilter(4)";
158    PageFilter pageFilter =
159      doTestFilter(filterString, PageFilter.class);
160    long pageSize = pageFilter.getPageSize();
161    assertEquals(4, pageSize);
162
163    filterString = " PageFilter('123')";
164    try {
165      doTestFilter(filterString, PageFilter.class);
166      assertTrue(false);
167    } catch (IllegalArgumentException e) {
168      System.out.println("PageFilter needs an int as an argument");
169    }
170  }
171
172  @Test
173  public void testColumnPaginationFilter() throws IOException {
174    String filterString = "ColumnPaginationFilter(4, 6)";
175    ColumnPaginationFilter columnPaginationFilter =
176      doTestFilter(filterString, ColumnPaginationFilter.class);
177    int limit = columnPaginationFilter.getLimit();
178    assertEquals(4, limit);
179    int offset = columnPaginationFilter.getOffset();
180    assertEquals(6, offset);
181
182    filterString = " ColumnPaginationFilter('124')";
183    try {
184      doTestFilter(filterString, ColumnPaginationFilter.class);
185      assertTrue(false);
186    } catch (IllegalArgumentException e) {
187      System.out.println("ColumnPaginationFilter needs two arguments");
188    }
189
190    filterString = " ColumnPaginationFilter('4' , '123a')";
191    try {
192      doTestFilter(filterString, ColumnPaginationFilter.class);
193      assertTrue(false);
194    } catch (IllegalArgumentException e) {
195      System.out.println("ColumnPaginationFilter needs two ints as arguments");
196    }
197
198    filterString = " ColumnPaginationFilter('4' , '-123')";
199    try {
200      doTestFilter(filterString, ColumnPaginationFilter.class);
201      assertTrue(false);
202    } catch (IllegalArgumentException e) {
203      System.out.println("ColumnPaginationFilter arguments should not be negative");
204    }
205  }
206
207  @Test
208  public void testInclusiveStopFilter() throws IOException {
209    String filterString = "InclusiveStopFilter ('row 3')";
210    InclusiveStopFilter inclusiveStopFilter =
211      doTestFilter(filterString, InclusiveStopFilter.class);
212    byte [] stopRowKey = inclusiveStopFilter.getStopRowKey();
213    assertEquals("row 3", new String(stopRowKey, StandardCharsets.UTF_8));
214  }
215
216
217  @Test
218  public void testTimestampsFilter() throws IOException {
219    String filterString = "TimestampsFilter(9223372036854775806, 6)";
220    TimestampsFilter timestampsFilter =
221      doTestFilter(filterString, TimestampsFilter.class);
222    List<Long> timestamps = timestampsFilter.getTimestamps();
223    assertEquals(2, timestamps.size());
224    assertEquals(Long.valueOf(6), timestamps.get(0));
225
226    filterString = "TimestampsFilter()";
227    timestampsFilter = doTestFilter(filterString, TimestampsFilter.class);
228    timestamps = timestampsFilter.getTimestamps();
229    assertEquals(0, timestamps.size());
230
231    filterString = "TimestampsFilter(9223372036854775808, 6)";
232    try {
233      doTestFilter(filterString, ColumnPaginationFilter.class);
234      assertTrue(false);
235    } catch (IllegalArgumentException e) {
236      System.out.println("Long Argument was too large");
237    }
238
239    filterString = "TimestampsFilter(-45, 6)";
240    try {
241      doTestFilter(filterString, ColumnPaginationFilter.class);
242      assertTrue(false);
243    } catch (IllegalArgumentException e) {
244      System.out.println("Timestamp Arguments should not be negative");
245    }
246  }
247
248  @Test
249  public void testRowFilter() throws IOException {
250    String filterString = "RowFilter ( =,   'binary:regionse')";
251    RowFilter rowFilter =
252      doTestFilter(filterString, RowFilter.class);
253    assertEquals(CompareOperator.EQUAL, rowFilter.getCompareOperator());
254    assertTrue(rowFilter.getComparator() instanceof BinaryComparator);
255    BinaryComparator binaryComparator = (BinaryComparator) rowFilter.getComparator();
256    assertEquals("regionse", new String(binaryComparator.getValue(), StandardCharsets.UTF_8));
257  }
258
259  @Test
260  public void testFamilyFilter() throws IOException {
261    String filterString = "FamilyFilter(>=, 'binaryprefix:pre')";
262    FamilyFilter familyFilter =
263      doTestFilter(filterString, FamilyFilter.class);
264    assertEquals(CompareOperator.GREATER_OR_EQUAL, familyFilter.getCompareOperator());
265    assertTrue(familyFilter.getComparator() instanceof BinaryPrefixComparator);
266    BinaryPrefixComparator binaryPrefixComparator =
267      (BinaryPrefixComparator) familyFilter.getComparator();
268    assertEquals("pre", new String(binaryPrefixComparator.getValue(), StandardCharsets.UTF_8));
269  }
270
271  @Test
272  public void testQualifierFilter() throws IOException {
273    String filterString = "QualifierFilter(=, 'regexstring:pre*')";
274    QualifierFilter qualifierFilter =
275      doTestFilter(filterString, QualifierFilter.class);
276    assertEquals(CompareOperator.EQUAL, qualifierFilter.getCompareOperator());
277    assertTrue(qualifierFilter.getComparator() instanceof RegexStringComparator);
278    RegexStringComparator regexStringComparator =
279      (RegexStringComparator) qualifierFilter.getComparator();
280    assertEquals("pre*", new String(regexStringComparator.getValue(), StandardCharsets.UTF_8));
281  }
282
283  @Test
284  public void testQualifierFilterNoCase() throws IOException {
285    String filterString = "QualifierFilter(=, 'regexstringnocase:pre*')";
286    QualifierFilter qualifierFilter =
287      doTestFilter(filterString, QualifierFilter.class);
288    assertEquals(CompareOperator.EQUAL, qualifierFilter.getCompareOperator());
289    assertTrue(qualifierFilter.getComparator() instanceof RegexStringComparator);
290    RegexStringComparator regexStringComparator =
291      (RegexStringComparator) qualifierFilter.getComparator();
292    assertEquals("pre*", new String(regexStringComparator.getValue(), StandardCharsets.UTF_8));
293    int regexComparatorFlags = regexStringComparator.getEngine().getFlags();
294    assertEquals(Pattern.CASE_INSENSITIVE | Pattern.DOTALL, regexComparatorFlags);
295  }
296
297  @Test
298  public void testValueFilter() throws IOException {
299    String filterString = "ValueFilter(!=, 'substring:pre')";
300    ValueFilter valueFilter =
301      doTestFilter(filterString, ValueFilter.class);
302    assertEquals(CompareOperator.NOT_EQUAL, valueFilter.getCompareOperator());
303    assertTrue(valueFilter.getComparator() instanceof SubstringComparator);
304    SubstringComparator substringComparator =
305      (SubstringComparator) valueFilter.getComparator();
306    assertEquals("pre", new String(substringComparator.getValue(), StandardCharsets.UTF_8));
307  }
308
309  @Test
310  public void testColumnRangeFilter() throws IOException {
311    String filterString = "ColumnRangeFilter('abc', true, 'xyz', false)";
312    ColumnRangeFilter columnRangeFilter =
313      doTestFilter(filterString, ColumnRangeFilter.class);
314    assertEquals("abc", new String(columnRangeFilter.getMinColumn(), StandardCharsets.UTF_8));
315    assertEquals("xyz", new String(columnRangeFilter.getMaxColumn(), StandardCharsets.UTF_8));
316    assertTrue(columnRangeFilter.isMinColumnInclusive());
317    assertFalse(columnRangeFilter.isMaxColumnInclusive());
318  }
319
320  @Test
321  public void testDependentColumnFilter() throws IOException {
322    String filterString = "DependentColumnFilter('family', 'qualifier', true, =, 'binary:abc')";
323    DependentColumnFilter dependentColumnFilter =
324      doTestFilter(filterString, DependentColumnFilter.class);
325    assertEquals("family", new String(dependentColumnFilter.getFamily(), StandardCharsets.UTF_8));
326    assertEquals("qualifier",
327        new String(dependentColumnFilter.getQualifier(), StandardCharsets.UTF_8));
328    assertTrue(dependentColumnFilter.getDropDependentColumn());
329    assertEquals(CompareOperator.EQUAL, dependentColumnFilter.getCompareOperator());
330    assertTrue(dependentColumnFilter.getComparator() instanceof BinaryComparator);
331    BinaryComparator binaryComparator = (BinaryComparator)dependentColumnFilter.getComparator();
332    assertEquals("abc", new String(binaryComparator.getValue(), StandardCharsets.UTF_8));
333  }
334
335  @Test
336  public void testSingleColumnValueFilter() throws IOException {
337    String filterString = "SingleColumnValueFilter " +
338      "('family', 'qualifier', >=, 'binary:a', true, false)";
339    SingleColumnValueFilter singleColumnValueFilter =
340      doTestFilter(filterString, SingleColumnValueFilter.class);
341    assertEquals("family", new String(singleColumnValueFilter.getFamily(), StandardCharsets.UTF_8));
342    assertEquals("qualifier",
343        new String(singleColumnValueFilter.getQualifier(), StandardCharsets.UTF_8));
344    assertEquals(CompareOperator.GREATER_OR_EQUAL, singleColumnValueFilter.getCompareOperator());
345    assertTrue(singleColumnValueFilter.getComparator() instanceof BinaryComparator);
346    BinaryComparator binaryComparator = (BinaryComparator) singleColumnValueFilter.getComparator();
347    assertEquals("a", new String(binaryComparator.getValue(), StandardCharsets.UTF_8));
348    assertTrue(singleColumnValueFilter.getFilterIfMissing());
349    assertFalse(singleColumnValueFilter.getLatestVersionOnly());
350
351
352    filterString = "SingleColumnValueFilter ('family', 'qualifier', >, 'binaryprefix:a')";
353    singleColumnValueFilter = doTestFilter(filterString, SingleColumnValueFilter.class);
354    assertEquals("family", new String(singleColumnValueFilter.getFamily(), StandardCharsets.UTF_8));
355    assertEquals("qualifier",
356        new String(singleColumnValueFilter.getQualifier(), StandardCharsets.UTF_8));
357    assertEquals(CompareOperator.GREATER, singleColumnValueFilter.getCompareOperator());
358    assertTrue(singleColumnValueFilter.getComparator() instanceof BinaryPrefixComparator);
359    BinaryPrefixComparator binaryPrefixComparator =
360      (BinaryPrefixComparator) singleColumnValueFilter.getComparator();
361    assertEquals("a", new String(binaryPrefixComparator.getValue(), StandardCharsets.UTF_8));
362    assertFalse(singleColumnValueFilter.getFilterIfMissing());
363    assertTrue(singleColumnValueFilter.getLatestVersionOnly());
364  }
365
366  @Test
367  public void testSingleColumnValueExcludeFilter() throws IOException {
368    String filterString =
369      "SingleColumnValueExcludeFilter ('family', 'qualifier', <, 'binaryprefix:a')";
370    SingleColumnValueExcludeFilter singleColumnValueExcludeFilter =
371      doTestFilter(filterString, SingleColumnValueExcludeFilter.class);
372    assertEquals(CompareOperator.LESS, singleColumnValueExcludeFilter.getCompareOperator());
373    assertEquals("family",
374        new String(singleColumnValueExcludeFilter.getFamily(), StandardCharsets.UTF_8));
375    assertEquals("qualifier",
376        new String(singleColumnValueExcludeFilter.getQualifier(), StandardCharsets.UTF_8));
377    assertEquals("a", new String(singleColumnValueExcludeFilter.getComparator().getValue(),
378        StandardCharsets.UTF_8));
379    assertFalse(singleColumnValueExcludeFilter.getFilterIfMissing());
380    assertTrue(singleColumnValueExcludeFilter.getLatestVersionOnly());
381
382    filterString = "SingleColumnValueExcludeFilter " +
383      "('family', 'qualifier', <=, 'binaryprefix:a', true, false)";
384    singleColumnValueExcludeFilter =
385      doTestFilter(filterString, SingleColumnValueExcludeFilter.class);
386    assertEquals("family",
387        new String(singleColumnValueExcludeFilter.getFamily(), StandardCharsets.UTF_8));
388    assertEquals("qualifier",
389        new String(singleColumnValueExcludeFilter.getQualifier(), StandardCharsets.UTF_8));
390    assertEquals(CompareOperator.LESS_OR_EQUAL,
391        singleColumnValueExcludeFilter.getCompareOperator());
392    assertTrue(singleColumnValueExcludeFilter.getComparator() instanceof BinaryPrefixComparator);
393    BinaryPrefixComparator binaryPrefixComparator =
394      (BinaryPrefixComparator) singleColumnValueExcludeFilter.getComparator();
395    assertEquals("a", new String(binaryPrefixComparator.getValue(), StandardCharsets.UTF_8));
396    assertTrue(singleColumnValueExcludeFilter.getFilterIfMissing());
397    assertFalse(singleColumnValueExcludeFilter.getLatestVersionOnly());
398  }
399
400  @Test
401  public void testSkipFilter() throws IOException {
402    String filterString = "SKIP ValueFilter( =,  'binary:0')";
403    SkipFilter skipFilter =
404      doTestFilter(filterString, SkipFilter.class);
405    assertTrue(skipFilter.getFilter() instanceof ValueFilter);
406    ValueFilter valueFilter = (ValueFilter) skipFilter.getFilter();
407
408    assertEquals(CompareOperator.EQUAL, valueFilter.getCompareOperator());
409    assertTrue(valueFilter.getComparator() instanceof BinaryComparator);
410    BinaryComparator binaryComparator = (BinaryComparator) valueFilter.getComparator();
411    assertEquals("0", new String(binaryComparator.getValue(), StandardCharsets.UTF_8));
412  }
413
414  @Test
415  public void testWhileFilter() throws IOException {
416    String filterString = " WHILE   RowFilter ( !=, 'binary:row1')";
417    WhileMatchFilter whileMatchFilter =
418      doTestFilter(filterString, WhileMatchFilter.class);
419    assertTrue(whileMatchFilter.getFilter() instanceof RowFilter);
420    RowFilter rowFilter = (RowFilter) whileMatchFilter.getFilter();
421
422    assertEquals(CompareOperator.NOT_EQUAL, rowFilter.getCompareOperator());
423    assertTrue(rowFilter.getComparator() instanceof BinaryComparator);
424    BinaryComparator binaryComparator = (BinaryComparator) rowFilter.getComparator();
425    assertEquals("row1", new String(binaryComparator.getValue(), StandardCharsets.UTF_8));
426  }
427
428  @Test
429  public void testCompoundFilter1() throws IOException {
430    String filterString = " (PrefixFilter ('realtime')AND  FirstKeyOnlyFilter())";
431    FilterList filterList =
432      doTestFilter(filterString, FilterList.class);
433    ArrayList<Filter> filters = (ArrayList<Filter>) filterList.getFilters();
434
435    assertTrue(filters.get(0) instanceof PrefixFilter);
436    assertTrue(filters.get(1) instanceof FirstKeyOnlyFilter);
437    PrefixFilter PrefixFilter = (PrefixFilter) filters.get(0);
438    byte [] prefix = PrefixFilter.getPrefix();
439    assertEquals("realtime", new String(prefix, StandardCharsets.UTF_8));
440    FirstKeyOnlyFilter firstKeyOnlyFilter = (FirstKeyOnlyFilter) filters.get(1);
441  }
442
443  @Test
444  public void testCompoundFilter2() throws IOException {
445    String filterString = "(PrefixFilter('realtime') AND QualifierFilter (>=, 'binary:e'))" +
446      "OR FamilyFilter (=, 'binary:qualifier') ";
447    FilterList filterList =
448      doTestFilter(filterString, FilterList.class);
449    ArrayList<Filter> filterListFilters = (ArrayList<Filter>) filterList.getFilters();
450    assertTrue(filterListFilters.get(0) instanceof FilterList);
451    assertTrue(filterListFilters.get(1) instanceof FamilyFilter);
452    assertEquals(FilterList.Operator.MUST_PASS_ONE, filterList.getOperator());
453
454    filterList = (FilterList) filterListFilters.get(0);
455    FamilyFilter familyFilter = (FamilyFilter) filterListFilters.get(1);
456
457    filterListFilters = (ArrayList<Filter>)filterList.getFilters();
458    assertTrue(filterListFilters.get(0) instanceof PrefixFilter);
459    assertTrue(filterListFilters.get(1) instanceof QualifierFilter);
460    assertEquals(FilterList.Operator.MUST_PASS_ALL, filterList.getOperator());
461
462    assertEquals(CompareOperator.EQUAL, familyFilter.getCompareOperator());
463    assertTrue(familyFilter.getComparator() instanceof BinaryComparator);
464    BinaryComparator binaryComparator = (BinaryComparator) familyFilter.getComparator();
465    assertEquals("qualifier", new String(binaryComparator.getValue(), StandardCharsets.UTF_8));
466
467    PrefixFilter prefixFilter = (PrefixFilter) filterListFilters.get(0);
468    byte [] prefix = prefixFilter.getPrefix();
469    assertEquals("realtime", new String(prefix, StandardCharsets.UTF_8));
470
471    QualifierFilter qualifierFilter = (QualifierFilter) filterListFilters.get(1);
472    assertEquals(CompareOperator.GREATER_OR_EQUAL, qualifierFilter.getCompareOperator());
473    assertTrue(qualifierFilter.getComparator() instanceof BinaryComparator);
474    binaryComparator = (BinaryComparator) qualifierFilter.getComparator();
475    assertEquals("e", new String(binaryComparator.getValue(), StandardCharsets.UTF_8));
476  }
477
478  @Test
479  public void testCompoundFilter3() throws IOException {
480    String filterString = " ColumnPrefixFilter ('realtime')AND  " +
481      "FirstKeyOnlyFilter() OR SKIP FamilyFilter(=, 'substring:hihi')";
482    FilterList filterList =
483      doTestFilter(filterString, FilterList.class);
484    ArrayList<Filter> filters = (ArrayList<Filter>) filterList.getFilters();
485
486    assertTrue(filters.get(0) instanceof FilterList);
487    assertTrue(filters.get(1) instanceof SkipFilter);
488
489    filterList = (FilterList) filters.get(0);
490    SkipFilter skipFilter = (SkipFilter) filters.get(1);
491
492    filters = (ArrayList<Filter>) filterList.getFilters();
493    assertTrue(filters.get(0) instanceof ColumnPrefixFilter);
494    assertTrue(filters.get(1) instanceof FirstKeyOnlyFilter);
495
496    ColumnPrefixFilter columnPrefixFilter = (ColumnPrefixFilter) filters.get(0);
497    byte [] columnPrefix = columnPrefixFilter.getPrefix();
498    assertEquals("realtime", new String(columnPrefix, StandardCharsets.UTF_8));
499
500    FirstKeyOnlyFilter firstKeyOnlyFilter = (FirstKeyOnlyFilter) filters.get(1);
501
502    assertTrue(skipFilter.getFilter() instanceof FamilyFilter);
503    FamilyFilter familyFilter = (FamilyFilter) skipFilter.getFilter();
504
505    assertEquals(CompareOperator.EQUAL, familyFilter.getCompareOperator());
506    assertTrue(familyFilter.getComparator() instanceof SubstringComparator);
507    SubstringComparator substringComparator =
508      (SubstringComparator) familyFilter.getComparator();
509    assertEquals("hihi", new String(substringComparator.getValue(), StandardCharsets.UTF_8));
510  }
511
512  @Test
513  public void testCompoundFilter4() throws IOException {
514    String filterString = " ColumnPrefixFilter ('realtime') OR " +
515      "FirstKeyOnlyFilter() OR SKIP FamilyFilter(=, 'substring:hihi')";
516    FilterList filterList =
517      doTestFilter(filterString, FilterList.class);
518    ArrayList<Filter> filters = (ArrayList<Filter>) filterList.getFilters();
519
520    assertTrue(filters.get(0) instanceof ColumnPrefixFilter);
521    assertTrue(filters.get(1) instanceof FirstKeyOnlyFilter);
522    assertTrue(filters.get(2) instanceof SkipFilter);
523
524    ColumnPrefixFilter columnPrefixFilter = (ColumnPrefixFilter) filters.get(0);
525    FirstKeyOnlyFilter firstKeyOnlyFilter = (FirstKeyOnlyFilter) filters.get(1);
526    SkipFilter skipFilter = (SkipFilter) filters.get(2);
527
528    byte [] columnPrefix = columnPrefixFilter.getPrefix();
529    assertEquals("realtime", new String(columnPrefix, StandardCharsets.UTF_8));
530
531    assertTrue(skipFilter.getFilter() instanceof FamilyFilter);
532    FamilyFilter familyFilter = (FamilyFilter) skipFilter.getFilter();
533
534    assertEquals(CompareOperator.EQUAL, familyFilter.getCompareOperator());
535    assertTrue(familyFilter.getComparator() instanceof SubstringComparator);
536    SubstringComparator substringComparator =
537      (SubstringComparator) familyFilter.getComparator();
538    assertEquals("hihi", new String(substringComparator.getValue(), StandardCharsets.UTF_8));
539  }
540
541  @Test
542  public void testCompoundFilter5() throws IOException {
543    String filterStr = "(ValueFilter(!=, 'substring:pre'))";
544    ValueFilter valueFilter = doTestFilter(filterStr, ValueFilter.class);
545    assertTrue(valueFilter.getComparator() instanceof SubstringComparator);
546
547    filterStr = "(ValueFilter(>=,'binary:x') AND (ValueFilter(<=,'binary:y')))"
548            + " OR ValueFilter(=,'binary:ab')";
549    filter = f.parseFilterString(filterStr);
550    assertTrue(filter instanceof FilterList);
551    List<Filter> list = ((FilterList) filter).getFilters();
552    assertEquals(2, list.size());
553    assertTrue(list.get(0) instanceof FilterList);
554    assertTrue(list.get(1) instanceof ValueFilter);
555  }
556
557  @Test
558  public void testIncorrectCompareOperator() throws IOException {
559    String filterString = "RowFilter ('>>' , 'binary:region')";
560    try {
561      doTestFilter(filterString, RowFilter.class);
562      assertTrue(false);
563    } catch (IllegalArgumentException e) {
564      System.out.println("Incorrect compare operator >>");
565    }
566  }
567
568  @Test
569  public void testIncorrectComparatorType() throws IOException {
570    String  filterString = "RowFilter ('>=' , 'binaryoperator:region')";
571    try {
572      doTestFilter(filterString, RowFilter.class);
573      assertTrue(false);
574    } catch (IllegalArgumentException e) {
575      System.out.println("Incorrect comparator type: binaryoperator");
576    }
577
578    filterString = "RowFilter ('>=' 'regexstring:pre*')";
579    try {
580      doTestFilter(filterString, RowFilter.class);
581      assertTrue(false);
582    } catch (IllegalArgumentException e) {
583      System.out.println("RegexStringComparator can only be used with EQUAL or NOT_EQUAL");
584    }
585
586    filterString = "SingleColumnValueFilter" +
587      " ('family', 'qualifier', '>=', 'substring:a', 'true', 'false')')";
588    try {
589      doTestFilter(filterString, RowFilter.class);
590      assertTrue(false);
591    } catch (IllegalArgumentException e) {
592      System.out.println("SubtringComparator can only be used with EQUAL or NOT_EQUAL");
593    }
594  }
595
596  @Test
597  public void testPrecedence1() throws IOException {
598    String filterString = " (PrefixFilter ('realtime')AND  FirstKeyOnlyFilter()" +
599      " OR KeyOnlyFilter())";
600    FilterList filterList =
601      doTestFilter(filterString, FilterList.class);
602
603    ArrayList<Filter> filters = (ArrayList<Filter>) filterList.getFilters();
604
605    assertTrue(filters.get(0) instanceof FilterList);
606    assertTrue(filters.get(1) instanceof KeyOnlyFilter);
607
608    filterList = (FilterList) filters.get(0);
609    filters = (ArrayList<Filter>) filterList.getFilters();
610
611    assertTrue(filters.get(0) instanceof PrefixFilter);
612    assertTrue(filters.get(1) instanceof FirstKeyOnlyFilter);
613
614    PrefixFilter prefixFilter = (PrefixFilter)filters.get(0);
615    byte [] prefix = prefixFilter.getPrefix();
616    assertEquals("realtime", new String(prefix, StandardCharsets.UTF_8));
617  }
618
619  @Test
620  public void testPrecedence2() throws IOException {
621    String filterString = " PrefixFilter ('realtime')AND  SKIP FirstKeyOnlyFilter()" +
622      "OR KeyOnlyFilter()";
623    FilterList filterList =
624      doTestFilter(filterString, FilterList.class);
625    ArrayList<Filter> filters = (ArrayList<Filter>) filterList.getFilters();
626
627    assertTrue(filters.get(0) instanceof FilterList);
628    assertTrue(filters.get(1) instanceof KeyOnlyFilter);
629
630    filterList = (FilterList) filters.get(0);
631    filters = (ArrayList<Filter>) filterList.getFilters();
632
633    assertTrue(filters.get(0) instanceof PrefixFilter);
634    assertTrue(filters.get(1) instanceof SkipFilter);
635
636    PrefixFilter prefixFilter = (PrefixFilter)filters.get(0);
637    byte [] prefix = prefixFilter.getPrefix();
638    assertEquals("realtime", new String(prefix, StandardCharsets.UTF_8));
639
640    SkipFilter skipFilter = (SkipFilter)filters.get(1);
641    assertTrue(skipFilter.getFilter() instanceof FirstKeyOnlyFilter);
642  }
643
644  @Test
645  public void testUnescapedQuote1() throws IOException {
646    String filterString = "InclusiveStopFilter ('row''3')";
647    InclusiveStopFilter inclusiveStopFilter =
648      doTestFilter(filterString, InclusiveStopFilter.class);
649    byte [] stopRowKey = inclusiveStopFilter.getStopRowKey();
650    assertEquals("row'3", new String(stopRowKey, StandardCharsets.UTF_8));
651  }
652
653  @Test
654  public void testUnescapedQuote2() throws IOException {
655    String filterString = "InclusiveStopFilter ('row''3''')";
656    InclusiveStopFilter inclusiveStopFilter =
657      doTestFilter(filterString, InclusiveStopFilter.class);
658    byte [] stopRowKey = inclusiveStopFilter.getStopRowKey();
659    assertEquals("row'3'", new String(stopRowKey, StandardCharsets.UTF_8));
660  }
661
662  @Test
663  public void testUnescapedQuote3() throws IOException {
664    String filterString = " InclusiveStopFilter ('''')";
665    InclusiveStopFilter inclusiveStopFilter = doTestFilter(filterString, InclusiveStopFilter.class);
666    byte [] stopRowKey = inclusiveStopFilter.getStopRowKey();
667    assertEquals("'", new String(stopRowKey, StandardCharsets.UTF_8));
668  }
669
670  @Test
671  public void testIncorrectFilterString() throws IOException {
672    String filterString = "()";
673    byte [] filterStringAsByteArray = Bytes.toBytes(filterString);
674    try {
675      filter = f.parseFilterString(filterStringAsByteArray);
676      assertTrue(false);
677    } catch (IllegalArgumentException e) {
678      System.out.println(e.getMessage());
679    }
680  }
681
682  @Test
683  public void testCorrectFilterString() throws IOException {
684    String filterString = "(FirstKeyOnlyFilter())";
685    FirstKeyOnlyFilter firstKeyOnlyFilter = doTestFilter(filterString, FirstKeyOnlyFilter.class);
686  }
687
688  @Test
689  public void testRegisterFilter() {
690    ParseFilter.registerFilter("MyFilter", "some.class");
691
692    assertTrue(f.getSupportedFilters().contains("MyFilter"));
693  }
694
695  private <T extends Filter> T doTestFilter(String filterString, Class<T> clazz)
696      throws IOException {
697    byte [] filterStringAsByteArray = Bytes.toBytes(filterString);
698    filter = f.parseFilterString(filterStringAsByteArray);
699    assertEquals(clazz, filter.getClass());
700    return clazz.cast(filter);
701  }
702
703  @Test
704  public void testColumnValueFilter() throws IOException {
705    String filterString = "ColumnValueFilter ('family', 'qualifier', <, 'binaryprefix:value')";
706    ColumnValueFilter cvf = doTestFilter(filterString, ColumnValueFilter.class);
707    assertEquals("family", new String(cvf.getFamily(), StandardCharsets.UTF_8));
708    assertEquals("qualifier", new String(cvf.getQualifier(), StandardCharsets.UTF_8));
709    assertEquals(CompareOperator.LESS, cvf.getCompareOperator());
710    assertTrue(cvf.getComparator() instanceof BinaryPrefixComparator);
711    assertEquals("value", new String(cvf.getComparator().getValue(), StandardCharsets.UTF_8));
712  }
713}