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.assertFalse;
021import static org.junit.Assert.assertTrue;
022
023import java.io.IOException;
024import java.nio.ByteBuffer;
025import java.util.regex.Pattern;
026import org.apache.hadoop.hbase.ByteBufferKeyValue;
027import org.apache.hadoop.hbase.Cell;
028import org.apache.hadoop.hbase.CompareOperator;
029import org.apache.hadoop.hbase.HBaseClassTestRule;
030import org.apache.hadoop.hbase.KeyValue;
031import org.apache.hadoop.hbase.testclassification.FilterTests;
032import org.apache.hadoop.hbase.testclassification.SmallTests;
033import org.apache.hadoop.hbase.util.Bytes;
034import org.junit.Before;
035import org.junit.ClassRule;
036import org.junit.Test;
037import org.junit.experimental.categories.Category;
038
039/**
040 * Tests the value filter
041 */
042@Category({FilterTests.class, SmallTests.class})
043public class TestSingleColumnValueFilter {
044
045  @ClassRule
046  public static final HBaseClassTestRule CLASS_RULE =
047      HBaseClassTestRule.forClass(TestSingleColumnValueFilter.class);
048
049  private static final byte[] ROW = Bytes.toBytes("test");
050  private static final byte[] COLUMN_FAMILY = Bytes.toBytes("test");
051  private static final byte [] COLUMN_QUALIFIER = Bytes.toBytes("foo");
052  private static final byte[] VAL_1 = Bytes.toBytes("a");
053  private static final byte[] VAL_2 = Bytes.toBytes("ab");
054  private static final byte[] VAL_3 = Bytes.toBytes("abc");
055  private static final byte[] VAL_4 = Bytes.toBytes("abcd");
056  private static final byte[] FULLSTRING_1 =
057    Bytes.toBytes("The quick brown fox jumps over the lazy dog.");
058  private static final byte[] FULLSTRING_2 =
059    Bytes.toBytes("The slow grey fox trips over the lazy dog.");
060  private static final String QUICK_SUBSTR = "quick";
061  private static final String QUICK_REGEX = ".+quick.+";
062  private static final Pattern QUICK_PATTERN = Pattern.compile("QuIcK", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
063
064  Filter basicFilter;
065  Filter nullFilter;
066  Filter substrFilter;
067  Filter regexFilter;
068  Filter regexPatternFilter;
069
070  @Before
071  public void setUp() throws Exception {
072    basicFilter = basicFilterNew();
073    nullFilter = nullFilterNew();
074    substrFilter = substrFilterNew();
075    regexFilter = regexFilterNew();
076    regexPatternFilter = regexFilterNew(QUICK_PATTERN);
077  }
078
079  private Filter basicFilterNew() {
080    return new SingleColumnValueFilter(COLUMN_FAMILY, COLUMN_QUALIFIER,
081    CompareOperator.GREATER_OR_EQUAL, VAL_2);
082  }
083
084  private Filter nullFilterNew() {
085    return new SingleColumnValueFilter(COLUMN_FAMILY, COLUMN_QUALIFIER, CompareOperator.NOT_EQUAL,
086        new NullComparator());
087  }
088
089  private Filter substrFilterNew() {
090    return new SingleColumnValueFilter(COLUMN_FAMILY, COLUMN_QUALIFIER,
091    CompareOperator.EQUAL,
092      new SubstringComparator(QUICK_SUBSTR));
093  }
094
095  private Filter regexFilterNew() {
096    return new SingleColumnValueFilter(COLUMN_FAMILY, COLUMN_QUALIFIER,
097    CompareOperator.EQUAL,
098      new RegexStringComparator(QUICK_REGEX));
099  }
100
101  private Filter regexFilterNew(Pattern pattern) {
102    return new SingleColumnValueFilter(COLUMN_FAMILY, COLUMN_QUALIFIER,
103    CompareOperator.EQUAL,
104        new RegexStringComparator(pattern.pattern(), pattern.flags()));
105  }
106
107  @Test
108  public void testLongComparator() throws IOException {
109    Filter filter = new SingleColumnValueFilter(COLUMN_FAMILY,
110        COLUMN_QUALIFIER, CompareOperator.GREATER, new LongComparator(100L));
111    KeyValue cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
112      Bytes.toBytes(1L));
113    assertTrue("less than", filter.filterCell(cell) == Filter.ReturnCode.NEXT_ROW);
114    filter.reset();
115    byte[] buffer = cell.getBuffer();
116    Cell c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
117    assertTrue("less than", filter.filterCell(c) == Filter.ReturnCode.NEXT_ROW);
118    filter.reset();
119
120    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
121      Bytes.toBytes(100L));
122    assertTrue("Equals 100", filter.filterCell(cell) == Filter.ReturnCode.NEXT_ROW);
123    filter.reset();
124    buffer = cell.getBuffer();
125    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
126    assertTrue("Equals 100", filter.filterCell(c) == Filter.ReturnCode.NEXT_ROW);
127    filter.reset();
128
129    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
130      Bytes.toBytes(120L));
131    assertTrue("include 120", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
132    filter.reset();
133    buffer = cell.getBuffer();
134    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
135    assertTrue("include 120", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
136  }
137
138  private void basicFilterTests(SingleColumnValueFilter filter)
139      throws Exception {
140    KeyValue cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_2);
141    assertTrue("basicFilter1", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
142    byte[] buffer = cell.getBuffer();
143    Cell c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
144    assertTrue("basicFilter1", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
145    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_3);
146    assertTrue("basicFilter2", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
147    buffer = cell.getBuffer();
148    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
149    assertTrue("basicFilter2", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
150    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_4);
151    assertTrue("basicFilter3", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
152    buffer = cell.getBuffer();
153    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
154    assertTrue("basicFilter3", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
155    assertFalse("basicFilterNotNull", filter.filterRow());
156    filter.reset();
157    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_1);
158    assertTrue("basicFilter4", filter.filterCell(cell) == Filter.ReturnCode.NEXT_ROW);
159    buffer = cell.getBuffer();
160    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
161    assertTrue("basicFilter4", filter.filterCell(c) == Filter.ReturnCode.NEXT_ROW);
162    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_2);
163    assertTrue("basicFilter4", filter.filterCell(cell) == Filter.ReturnCode.NEXT_ROW);
164    buffer = cell.getBuffer();
165    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
166    assertTrue("basicFilter4", filter.filterCell(c) == Filter.ReturnCode.NEXT_ROW);
167    assertFalse("basicFilterAllRemaining", filter.filterAllRemaining());
168    assertTrue("basicFilterNotNull", filter.filterRow());
169    filter.reset();
170    filter.setLatestVersionOnly(false);
171    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_1);
172    assertTrue("basicFilter5", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
173    buffer = cell.getBuffer();
174    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
175    assertTrue("basicFilter5", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
176    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_2);
177    assertTrue("basicFilter5", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
178    buffer = cell.getBuffer();
179    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
180    assertTrue("basicFilter5", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
181    assertFalse("basicFilterNotNull", filter.filterRow());
182  }
183
184  private void nullFilterTests(Filter filter) throws Exception {
185    ((SingleColumnValueFilter) filter).setFilterIfMissing(true);
186    KeyValue cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, FULLSTRING_1);
187    assertTrue("null1", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
188    byte[] buffer = cell.getBuffer();
189    Cell c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
190    assertTrue("null1", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
191    assertFalse("null1FilterRow", filter.filterRow());
192    filter.reset();
193    cell = new KeyValue(ROW, COLUMN_FAMILY, Bytes.toBytes("qual2"), FULLSTRING_2);
194    assertTrue("null2", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
195    buffer = cell.getBuffer();
196    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
197    assertTrue("null2", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
198    assertTrue("null2FilterRow", filter.filterRow());
199  }
200
201  private void substrFilterTests(Filter filter)
202      throws Exception {
203    KeyValue cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
204      FULLSTRING_1);
205    assertTrue("substrTrue",
206      filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
207    byte[] buffer = cell.getBuffer();
208    Cell c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
209    assertTrue("substrTrue", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
210    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
211      FULLSTRING_2);
212    assertTrue("substrFalse", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
213    buffer = cell.getBuffer();
214    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
215    assertTrue("substrFalse", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
216    assertFalse("substrFilterAllRemaining", filter.filterAllRemaining());
217    assertFalse("substrFilterNotNull", filter.filterRow());
218  }
219
220  private void regexFilterTests(Filter filter)
221      throws Exception {
222    KeyValue cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
223      FULLSTRING_1);
224    assertTrue("regexTrue",
225      filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
226    byte[] buffer = cell.getBuffer();
227    Cell c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
228    assertTrue("regexTrue", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
229    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
230      FULLSTRING_2);
231    assertTrue("regexFalse", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
232    buffer = cell.getBuffer();
233    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
234    assertTrue("regexFalse", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
235    assertFalse("regexFilterAllRemaining", filter.filterAllRemaining());
236    assertFalse("regexFilterNotNull", filter.filterRow());
237  }
238
239  private void regexPatternFilterTests(Filter filter)
240      throws Exception {
241    KeyValue cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
242      FULLSTRING_1);
243    assertTrue("regexTrue",
244      filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
245    byte[] buffer = cell.getBuffer();
246    Cell c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
247    assertTrue("regexTrue", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
248    assertFalse("regexFilterAllRemaining", filter.filterAllRemaining());
249    assertFalse("regexFilterNotNull", filter.filterRow());
250  }
251
252  private Filter serializationTest(Filter filter)
253      throws Exception {
254    // Decompose filter to bytes.
255    byte[] buffer = filter.toByteArray();
256
257    // Recompose filter.
258    Filter newFilter = SingleColumnValueFilter.parseFrom(buffer);
259    return newFilter;
260  }
261
262  /**
263   * Tests identification of the stop row
264   * @throws Exception
265   */
266  @Test
267  public void testStop() throws Exception {
268    basicFilterTests((SingleColumnValueFilter) basicFilter);
269    nullFilterTests(nullFilter);
270    substrFilterTests(substrFilter);
271    regexFilterTests(regexFilter);
272    regexPatternFilterTests(regexPatternFilter);
273  }
274
275  /**
276   * Tests serialization
277   * @throws Exception
278   */
279  @Test
280  public void testSerialization() throws Exception {
281    Filter newFilter = serializationTest(basicFilter);
282    basicFilterTests((SingleColumnValueFilter)newFilter);
283    newFilter = serializationTest(nullFilter);
284    nullFilterTests(newFilter);
285    newFilter = serializationTest(substrFilter);
286    substrFilterTests(newFilter);
287    newFilter = serializationTest(regexFilter);
288    regexFilterTests(newFilter);
289    newFilter = serializationTest(regexPatternFilter);
290    regexPatternFilterTests(newFilter);
291  }
292
293}
294