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