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.rest;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertNotNull;
022import static org.junit.Assert.assertTrue;
023
024import java.io.ByteArrayInputStream;
025import java.io.StringWriter;
026import java.util.ArrayList;
027import java.util.Arrays;
028import java.util.Iterator;
029import java.util.List;
030import javax.xml.bind.JAXBContext;
031import javax.xml.bind.Marshaller;
032import javax.xml.bind.Unmarshaller;
033import org.apache.hadoop.hbase.CellUtil;
034import org.apache.hadoop.hbase.CompareOperator;
035import org.apache.hadoop.hbase.HBaseClassTestRule;
036import org.apache.hadoop.hbase.HBaseTestingUtility;
037import org.apache.hadoop.hbase.HColumnDescriptor;
038import org.apache.hadoop.hbase.HConstants;
039import org.apache.hadoop.hbase.HTableDescriptor;
040import org.apache.hadoop.hbase.KeyValue;
041import org.apache.hadoop.hbase.TableName;
042import org.apache.hadoop.hbase.client.Admin;
043import org.apache.hadoop.hbase.client.Delete;
044import org.apache.hadoop.hbase.client.Durability;
045import org.apache.hadoop.hbase.client.Put;
046import org.apache.hadoop.hbase.client.Scan;
047import org.apache.hadoop.hbase.client.Table;
048import org.apache.hadoop.hbase.filter.BinaryComparator;
049import org.apache.hadoop.hbase.filter.Filter;
050import org.apache.hadoop.hbase.filter.FilterList;
051import org.apache.hadoop.hbase.filter.FilterList.Operator;
052import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
053import org.apache.hadoop.hbase.filter.InclusiveStopFilter;
054import org.apache.hadoop.hbase.filter.PageFilter;
055import org.apache.hadoop.hbase.filter.PrefixFilter;
056import org.apache.hadoop.hbase.filter.QualifierFilter;
057import org.apache.hadoop.hbase.filter.RegexStringComparator;
058import org.apache.hadoop.hbase.filter.RowFilter;
059import org.apache.hadoop.hbase.filter.SkipFilter;
060import org.apache.hadoop.hbase.filter.SubstringComparator;
061import org.apache.hadoop.hbase.filter.ValueFilter;
062import org.apache.hadoop.hbase.rest.client.Client;
063import org.apache.hadoop.hbase.rest.client.Cluster;
064import org.apache.hadoop.hbase.rest.client.Response;
065import org.apache.hadoop.hbase.rest.model.CellModel;
066import org.apache.hadoop.hbase.rest.model.CellSetModel;
067import org.apache.hadoop.hbase.rest.model.RowModel;
068import org.apache.hadoop.hbase.rest.model.ScannerModel;
069import org.apache.hadoop.hbase.testclassification.MediumTests;
070import org.apache.hadoop.hbase.testclassification.RestTests;
071import org.apache.hadoop.hbase.util.Bytes;
072import org.junit.AfterClass;
073import org.junit.BeforeClass;
074import org.junit.ClassRule;
075import org.junit.Test;
076import org.junit.experimental.categories.Category;
077import org.slf4j.Logger;
078import org.slf4j.LoggerFactory;
079
080@Category({ RestTests.class, MediumTests.class })
081public class TestScannersWithFilters {
082  @ClassRule
083  public static final HBaseClassTestRule CLASS_RULE =
084    HBaseClassTestRule.forClass(TestScannersWithFilters.class);
085
086  private static final Logger LOG = LoggerFactory.getLogger(TestScannersWithFilters.class);
087
088  private static final TableName TABLE = TableName.valueOf("TestScannersWithFilters");
089
090  private static final byte[][] ROWS_ONE = { Bytes.toBytes("testRowOne-0"),
091    Bytes.toBytes("testRowOne-1"), Bytes.toBytes("testRowOne-2"), Bytes.toBytes("testRowOne-3") };
092
093  private static final byte[][] ROWS_TWO = { Bytes.toBytes("testRowTwo-0"),
094    Bytes.toBytes("testRowTwo-1"), Bytes.toBytes("testRowTwo-2"), Bytes.toBytes("testRowTwo-3") };
095
096  private static final byte[][] FAMILIES =
097    { Bytes.toBytes("testFamilyOne"), Bytes.toBytes("testFamilyTwo") };
098
099  private static final byte[][] QUALIFIERS_ONE =
100    { Bytes.toBytes("testQualifierOne-0"), Bytes.toBytes("testQualifierOne-1"),
101      Bytes.toBytes("testQualifierOne-2"), Bytes.toBytes("testQualifierOne-3") };
102
103  private static final byte[][] QUALIFIERS_TWO =
104    { Bytes.toBytes("testQualifierTwo-0"), Bytes.toBytes("testQualifierTwo-1"),
105      Bytes.toBytes("testQualifierTwo-2"), Bytes.toBytes("testQualifierTwo-3") };
106
107  private static final byte[][] VALUES =
108    { Bytes.toBytes("testValueOne"), Bytes.toBytes("testValueTwo") };
109
110  private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
111  private static final HBaseRESTTestingUtility REST_TEST_UTIL = new HBaseRESTTestingUtility();
112  private static Client client;
113  private static JAXBContext context;
114  private static Marshaller marshaller;
115  private static Unmarshaller unmarshaller;
116  private static long numRows = (long) ROWS_ONE.length + ROWS_TWO.length;
117  private static long colsPerRow = (long) FAMILIES.length * QUALIFIERS_ONE.length;
118
119  @BeforeClass
120  public static void setUpBeforeClass() throws Exception {
121    TEST_UTIL.startMiniCluster(3);
122    REST_TEST_UTIL.startServletContainer(TEST_UTIL.getConfiguration());
123    context = JAXBContext.newInstance(CellModel.class, CellSetModel.class, RowModel.class,
124      ScannerModel.class);
125    marshaller = context.createMarshaller();
126    unmarshaller = context.createUnmarshaller();
127    client = new Client(new Cluster().add("localhost", REST_TEST_UTIL.getServletPort()));
128    Admin admin = TEST_UTIL.getAdmin();
129    if (!admin.tableExists(TABLE)) {
130      HTableDescriptor htd = new HTableDescriptor(TABLE);
131      htd.addFamily(new HColumnDescriptor(FAMILIES[0]));
132      htd.addFamily(new HColumnDescriptor(FAMILIES[1]));
133      admin.createTable(htd);
134      Table table = TEST_UTIL.getConnection().getTable(TABLE);
135      // Insert first half
136      for (byte[] ROW : ROWS_ONE) {
137        Put p = new Put(ROW);
138        p.setDurability(Durability.SKIP_WAL);
139        for (byte[] QUALIFIER : QUALIFIERS_ONE) {
140          p.addColumn(FAMILIES[0], QUALIFIER, VALUES[0]);
141        }
142        table.put(p);
143      }
144      for (byte[] ROW : ROWS_TWO) {
145        Put p = new Put(ROW);
146        p.setDurability(Durability.SKIP_WAL);
147        for (byte[] QUALIFIER : QUALIFIERS_TWO) {
148          p.addColumn(FAMILIES[1], QUALIFIER, VALUES[1]);
149        }
150        table.put(p);
151      }
152
153      // Insert second half (reverse families)
154      for (byte[] ROW : ROWS_ONE) {
155        Put p = new Put(ROW);
156        p.setDurability(Durability.SKIP_WAL);
157        for (byte[] QUALIFIER : QUALIFIERS_ONE) {
158          p.addColumn(FAMILIES[1], QUALIFIER, VALUES[0]);
159        }
160        table.put(p);
161      }
162      for (byte[] ROW : ROWS_TWO) {
163        Put p = new Put(ROW);
164        p.setDurability(Durability.SKIP_WAL);
165        for (byte[] QUALIFIER : QUALIFIERS_TWO) {
166          p.addColumn(FAMILIES[0], QUALIFIER, VALUES[1]);
167        }
168        table.put(p);
169      }
170
171      // Delete the second qualifier from all rows and families
172      for (byte[] ROW : ROWS_ONE) {
173        Delete d = new Delete(ROW);
174        d.addColumns(FAMILIES[0], QUALIFIERS_ONE[1]);
175        d.addColumns(FAMILIES[1], QUALIFIERS_ONE[1]);
176        table.delete(d);
177      }
178      for (byte[] ROW : ROWS_TWO) {
179        Delete d = new Delete(ROW);
180        d.addColumns(FAMILIES[0], QUALIFIERS_TWO[1]);
181        d.addColumns(FAMILIES[1], QUALIFIERS_TWO[1]);
182        table.delete(d);
183      }
184      colsPerRow -= 2;
185
186      // Delete the second rows from both groups, one column at a time
187      for (byte[] QUALIFIER : QUALIFIERS_ONE) {
188        Delete d = new Delete(ROWS_ONE[1]);
189        d.addColumns(FAMILIES[0], QUALIFIER);
190        d.addColumns(FAMILIES[1], QUALIFIER);
191        table.delete(d);
192      }
193      for (byte[] QUALIFIER : QUALIFIERS_TWO) {
194        Delete d = new Delete(ROWS_TWO[1]);
195        d.addColumns(FAMILIES[0], QUALIFIER);
196        d.addColumns(FAMILIES[1], QUALIFIER);
197        table.delete(d);
198      }
199      numRows -= 2;
200      table.close();
201    }
202  }
203
204  @AfterClass
205  public static void tearDownAfterClass() throws Exception {
206    REST_TEST_UTIL.shutdownServletContainer();
207    TEST_UTIL.shutdownMiniCluster();
208  }
209
210  private static void verifyScan(Scan s, long expectedRows, long expectedKeys) throws Exception {
211    ScannerModel model = ScannerModel.fromScan(s);
212    model.setBatch(Integer.MAX_VALUE); // fetch it all at once
213    StringWriter writer = new StringWriter();
214    marshaller.marshal(model, writer);
215    LOG.debug(writer.toString());
216    byte[] body = Bytes.toBytes(writer.toString());
217    Response response = client.put("/" + TABLE + "/scanner", Constants.MIMETYPE_XML, body);
218    assertEquals(201, response.getCode());
219    String scannerURI = response.getLocation();
220    assertNotNull(scannerURI);
221
222    // get a cell set
223    response = client.get(scannerURI, Constants.MIMETYPE_XML);
224    assertEquals(200, response.getCode());
225    assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
226    CellSetModel cells =
227      (CellSetModel) unmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
228
229    int rows = cells.getRows().size();
230    assertEquals(
231      "Scanned too many rows! Only expected " + expectedRows + " total but scanned " + rows,
232      expectedRows, rows);
233    for (RowModel row : cells.getRows()) {
234      int count = row.getCells().size();
235      assertEquals("Expected " + expectedKeys + " keys per row but " + "returned " + count,
236        expectedKeys, count);
237    }
238
239    // delete the scanner
240    response = client.delete(scannerURI);
241    assertEquals(200, response.getCode());
242  }
243
244  private static void verifyScanFull(Scan s, KeyValue[] kvs) throws Exception {
245    ScannerModel model = ScannerModel.fromScan(s);
246    model.setBatch(Integer.MAX_VALUE); // fetch it all at once
247    StringWriter writer = new StringWriter();
248    marshaller.marshal(model, writer);
249    LOG.debug(writer.toString());
250    byte[] body = Bytes.toBytes(writer.toString());
251    Response response = client.put("/" + TABLE + "/scanner", Constants.MIMETYPE_XML, body);
252    assertEquals(201, response.getCode());
253    String scannerURI = response.getLocation();
254    assertNotNull(scannerURI);
255
256    // get a cell set
257    response = client.get(scannerURI, Constants.MIMETYPE_XML);
258    assertEquals(200, response.getCode());
259    assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
260    CellSetModel cellSet =
261      (CellSetModel) unmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
262
263    // delete the scanner
264    response = client.delete(scannerURI);
265    assertEquals(200, response.getCode());
266
267    int row = 0;
268    int idx = 0;
269    Iterator<RowModel> i = cellSet.getRows().iterator();
270    for (boolean done = true; done; row++) {
271      done = i.hasNext();
272      if (!done) {
273        break;
274      }
275
276      RowModel rowModel = i.next();
277      List<CellModel> cells = rowModel.getCells();
278      if (cells.isEmpty()) {
279        break;
280      }
281
282      assertTrue("Scanned too many keys! Only expected " + kvs.length
283        + " total but already scanned " + (cells.size() + idx), kvs.length >= idx + cells.size());
284      for (CellModel cell : cells) {
285        assertTrue("Row mismatch", Bytes.equals(rowModel.getKey(), CellUtil.cloneRow(kvs[idx])));
286        byte[][] split = CellUtil.parseColumn(cell.getColumn());
287        assertTrue("Family mismatch", Bytes.equals(split[0], CellUtil.cloneFamily(kvs[idx])));
288        assertTrue("Qualifier mismatch", Bytes.equals(split[1], CellUtil.cloneQualifier(kvs[idx])));
289        assertTrue("Value mismatch", Bytes.equals(cell.getValue(), CellUtil.cloneValue(kvs[idx])));
290        idx++;
291      }
292    }
293    assertEquals("Expected " + kvs.length + " total keys but scanned " + idx, kvs.length, idx);
294  }
295
296  private static void verifyScanNoEarlyOut(Scan s, long expectedRows, long expectedKeys)
297    throws Exception {
298    ScannerModel model = ScannerModel.fromScan(s);
299    model.setBatch(Integer.MAX_VALUE); // fetch it all at once
300    StringWriter writer = new StringWriter();
301    marshaller.marshal(model, writer);
302    LOG.debug(writer.toString());
303    byte[] body = Bytes.toBytes(writer.toString());
304    Response response = client.put("/" + TABLE + "/scanner", Constants.MIMETYPE_XML, body);
305    assertEquals(201, response.getCode());
306    String scannerURI = response.getLocation();
307    assertNotNull(scannerURI);
308
309    // get a cell set
310    response = client.get(scannerURI, Constants.MIMETYPE_XML);
311    assertEquals(200, response.getCode());
312    assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
313    CellSetModel cellSet =
314      (CellSetModel) unmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
315
316    // delete the scanner
317    response = client.delete(scannerURI);
318    assertEquals(200, response.getCode());
319
320    Iterator<RowModel> i = cellSet.getRows().iterator();
321    int j = 0;
322    for (boolean done = true; done; j++) {
323      done = i.hasNext();
324      if (!done) {
325        break;
326      }
327
328      RowModel rowModel = i.next();
329      List<CellModel> cells = rowModel.getCells();
330      if (cells.isEmpty()) {
331        break;
332      }
333
334      assertTrue("Scanned too many rows! Only expected " + expectedRows
335        + " total but already scanned " + (j + 1), expectedRows > j);
336      assertEquals("Expected " + expectedKeys + " keys per row but " + "returned " + cells.size(),
337        expectedKeys, cells.size());
338    }
339    assertEquals("Expected " + expectedRows + " rows but scanned " + j + " rows", expectedRows, j);
340  }
341
342  @Test
343  public void testNoFilter() throws Exception {
344    // No filter
345    long expectedRows = numRows;
346    long expectedKeys = colsPerRow;
347
348    // Both families
349    Scan s = new Scan();
350    verifyScan(s, expectedRows, expectedKeys);
351
352    // One family
353    s = new Scan();
354    s.addFamily(FAMILIES[0]);
355    verifyScan(s, expectedRows, expectedKeys / 2);
356  }
357
358  @Test
359  public void testPrefixFilter() throws Exception {
360    // Grab rows from group one (half of total)
361    long expectedRows = numRows / 2;
362    long expectedKeys = colsPerRow;
363    Scan s = new Scan();
364    s.setFilter(new PrefixFilter(Bytes.toBytes("testRowOne")));
365    verifyScan(s, expectedRows, expectedKeys);
366  }
367
368  @Test
369  public void testPageFilter() throws Exception {
370    // KVs in first 6 rows
371    KeyValue[] expectedKVs = {
372      // testRowOne-0
373      new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
374      new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
375      new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
376      new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
377      new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
378      new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
379      // testRowOne-2
380      new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
381      new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
382      new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
383      new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
384      new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
385      new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
386      // testRowOne-3
387      new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
388      new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
389      new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
390      new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
391      new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
392      new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
393      // testRowTwo-0
394      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
395      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
396      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
397      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
398      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
399      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
400      // testRowTwo-2
401      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
402      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
403      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
404      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
405      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
406      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
407      // testRowTwo-3
408      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
409      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
410      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
411      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
412      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
413      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]) };
414
415    // Grab all 6 rows
416    long expectedRows = 6;
417    long expectedKeys = colsPerRow;
418    Scan s = new Scan();
419    s.setFilter(new PageFilter(expectedRows));
420    verifyScan(s, expectedRows, expectedKeys);
421    s.setFilter(new PageFilter(expectedRows));
422    verifyScanFull(s, expectedKVs);
423
424    // Grab first 4 rows (6 cols per row)
425    expectedRows = 4;
426    expectedKeys = colsPerRow;
427    s = new Scan();
428    s.setFilter(new PageFilter(expectedRows));
429    verifyScan(s, expectedRows, expectedKeys);
430    s.setFilter(new PageFilter(expectedRows));
431    verifyScanFull(s, Arrays.copyOf(expectedKVs, 24));
432
433    // Grab first 2 rows
434    expectedRows = 2;
435    expectedKeys = colsPerRow;
436    s = new Scan();
437    s.setFilter(new PageFilter(expectedRows));
438    verifyScan(s, expectedRows, expectedKeys);
439    s.setFilter(new PageFilter(expectedRows));
440    verifyScanFull(s, Arrays.copyOf(expectedKVs, 12));
441
442    // Grab first row
443    expectedRows = 1;
444    expectedKeys = colsPerRow;
445    s = new Scan();
446    s.setFilter(new PageFilter(expectedRows));
447    verifyScan(s, expectedRows, expectedKeys);
448    s.setFilter(new PageFilter(expectedRows));
449    verifyScanFull(s, Arrays.copyOf(expectedKVs, 6));
450  }
451
452  @Test
453  public void testInclusiveStopFilter() throws Exception {
454    // Grab rows from group one
455
456    // If we just use start/stop row, we get total/2 - 1 rows
457    long expectedRows = (numRows / 2) - 1;
458    long expectedKeys = colsPerRow;
459    Scan s = new Scan(Bytes.toBytes("testRowOne-0"), Bytes.toBytes("testRowOne-3"));
460    verifyScan(s, expectedRows, expectedKeys);
461
462    // Now use start row with inclusive stop filter
463    expectedRows = numRows / 2;
464    s = new Scan(Bytes.toBytes("testRowOne-0"));
465    s.setFilter(new InclusiveStopFilter(Bytes.toBytes("testRowOne-3")));
466    verifyScan(s, expectedRows, expectedKeys);
467
468    // Grab rows from group two
469
470    // If we just use start/stop row, we get total/2 - 1 rows
471    expectedRows = (numRows / 2) - 1;
472    expectedKeys = colsPerRow;
473    s = new Scan(Bytes.toBytes("testRowTwo-0"), Bytes.toBytes("testRowTwo-3"));
474    verifyScan(s, expectedRows, expectedKeys);
475
476    // Now use start row with inclusive stop filter
477    expectedRows = numRows / 2;
478    s = new Scan(Bytes.toBytes("testRowTwo-0"));
479    s.setFilter(new InclusiveStopFilter(Bytes.toBytes("testRowTwo-3")));
480    verifyScan(s, expectedRows, expectedKeys);
481  }
482
483  @Test
484  public void testQualifierFilter() throws Exception {
485    // Match two keys (one from each family) in half the rows
486    long expectedRows = numRows / 2;
487    long expectedKeys = 2;
488    Filter f = new QualifierFilter(CompareOperator.EQUAL,
489      new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
490    Scan s = new Scan();
491    s.setFilter(f);
492    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
493
494    // Match keys less than same qualifier
495    // Expect only two keys (one from each family) in half the rows
496    expectedRows = numRows / 2;
497    expectedKeys = 2;
498    f = new QualifierFilter(CompareOperator.LESS,
499      new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
500    s = new Scan();
501    s.setFilter(f);
502    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
503
504    // Match keys less than or equal. Expect four keys (two from each family) in half the rows
505    expectedRows = numRows / 2;
506    expectedKeys = 4;
507    f = new QualifierFilter(CompareOperator.LESS_OR_EQUAL,
508      new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
509    s = new Scan();
510    s.setFilter(f);
511    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
512
513    // Match keys not equal. Expect four keys (two from each family)
514    // Only look in first group of rows
515    expectedRows = numRows / 2;
516    expectedKeys = 4;
517    f = new QualifierFilter(CompareOperator.NOT_EQUAL,
518      new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
519    s = new Scan(HConstants.EMPTY_START_ROW, Bytes.toBytes("testRowTwo"));
520    s.setFilter(f);
521    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
522
523    // Match keys greater or equal. Expect four keys (two from each family)
524    // Only look in first group of rows
525    expectedRows = numRows / 2;
526    expectedKeys = 4;
527    f = new QualifierFilter(CompareOperator.GREATER_OR_EQUAL,
528      new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
529    s = new Scan(HConstants.EMPTY_START_ROW, Bytes.toBytes("testRowTwo"));
530    s.setFilter(f);
531    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
532
533    // Match keys greater. Expect two keys (one from each family)
534    // Only look in first group of rows
535    expectedRows = numRows / 2;
536    expectedKeys = 2;
537    f = new QualifierFilter(CompareOperator.GREATER,
538      new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
539    s = new Scan(HConstants.EMPTY_START_ROW, Bytes.toBytes("testRowTwo"));
540    s.setFilter(f);
541    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
542
543    // Match keys not equal to. Look across rows and fully validate the keys and ordering
544    // Expect varied numbers of keys, 4 per row in group one, 6 per row in group two
545    f = new QualifierFilter(CompareOperator.NOT_EQUAL, new BinaryComparator(QUALIFIERS_ONE[2]));
546    s = new Scan();
547    s.setFilter(f);
548
549    KeyValue[] kvs = {
550      // testRowOne-0
551      new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
552      new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
553      new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
554      new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
555      // testRowOne-2
556      new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
557      new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
558      new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
559      new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
560      // testRowOne-3
561      new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
562      new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
563      new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
564      new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
565      // testRowTwo-0
566      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
567      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
568      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
569      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
570      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
571      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
572      // testRowTwo-2
573      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
574      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
575      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
576      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
577      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
578      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
579      // testRowTwo-3
580      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
581      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
582      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
583      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
584      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
585      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]), };
586    verifyScanFull(s, kvs);
587
588    // Test across rows and groups with a regex. Filter out "test*-2"
589    // Expect 4 keys per row across both groups
590    f = new QualifierFilter(CompareOperator.NOT_EQUAL, new RegexStringComparator("test.+-2"));
591    s = new Scan();
592    s.setFilter(f);
593
594    kvs = new KeyValue[] {
595      // testRowOne-0
596      new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
597      new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
598      new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
599      new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
600      // testRowOne-2
601      new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
602      new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
603      new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
604      new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
605      // testRowOne-3
606      new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
607      new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
608      new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
609      new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
610      // testRowTwo-0
611      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
612      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
613      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
614      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
615      // testRowTwo-2
616      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
617      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
618      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
619      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
620      // testRowTwo-3
621      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
622      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
623      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
624      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]), };
625    verifyScanFull(s, kvs);
626  }
627
628  @Test
629  public void testRowFilter() throws Exception {
630    // Match a single row, all keys
631    long expectedRows = 1;
632    long expectedKeys = colsPerRow;
633    Filter f =
634      new RowFilter(CompareOperator.EQUAL, new BinaryComparator(Bytes.toBytes("testRowOne-2")));
635    Scan s = new Scan();
636    s.setFilter(f);
637    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
638
639    // Match a two rows, one from each group, using regex
640    expectedRows = 2;
641    expectedKeys = colsPerRow;
642    f = new RowFilter(CompareOperator.EQUAL, new RegexStringComparator("testRow.+-2"));
643    s = new Scan();
644    s.setFilter(f);
645    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
646
647    // Match rows less than
648    // Expect all keys in one row
649    expectedRows = 1;
650    expectedKeys = colsPerRow;
651    f = new RowFilter(CompareOperator.LESS, new BinaryComparator(Bytes.toBytes("testRowOne-2")));
652    s = new Scan();
653    s.setFilter(f);
654    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
655
656    // Match rows less than or equal
657    // Expect all keys in two rows
658    expectedRows = 2;
659    expectedKeys = colsPerRow;
660    f = new RowFilter(CompareOperator.LESS_OR_EQUAL,
661      new BinaryComparator(Bytes.toBytes("testRowOne-2")));
662    s = new Scan();
663    s.setFilter(f);
664    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
665
666    // Match rows not equal
667    // Expect all keys in all but one row
668    expectedRows = numRows - 1;
669    expectedKeys = colsPerRow;
670    f =
671      new RowFilter(CompareOperator.NOT_EQUAL, new BinaryComparator(Bytes.toBytes("testRowOne-2")));
672    s = new Scan();
673    s.setFilter(f);
674    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
675
676    // Match keys greater or equal
677    // Expect all keys in all but one row
678    expectedRows = numRows - 1;
679    expectedKeys = colsPerRow;
680    f = new RowFilter(CompareOperator.GREATER_OR_EQUAL,
681      new BinaryComparator(Bytes.toBytes("testRowOne-2")));
682    s = new Scan();
683    s.setFilter(f);
684    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
685
686    // Match keys greater
687    // Expect all keys in all but two rows
688    expectedRows = numRows - 2;
689    expectedKeys = colsPerRow;
690    f = new RowFilter(CompareOperator.GREATER, new BinaryComparator(Bytes.toBytes("testRowOne-2")));
691    s = new Scan();
692    s.setFilter(f);
693    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
694
695    // Match rows not equal to testRowTwo-2
696    // Look across rows and fully validate the keys and ordering
697    // Should see all keys in all rows but testRowTwo-2
698    f =
699      new RowFilter(CompareOperator.NOT_EQUAL, new BinaryComparator(Bytes.toBytes("testRowOne-2")));
700    s = new Scan();
701    s.setFilter(f);
702
703    KeyValue[] kvs = {
704      // testRowOne-0
705      new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
706      new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
707      new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
708      new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
709      new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
710      new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
711      // testRowOne-3
712      new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
713      new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
714      new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
715      new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
716      new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
717      new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
718      // testRowTwo-0
719      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
720      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
721      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
722      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
723      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
724      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
725      // testRowTwo-2
726      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
727      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
728      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
729      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
730      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
731      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
732      // testRowTwo-3
733      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
734      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
735      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
736      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
737      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
738      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]), };
739    verifyScanFull(s, kvs);
740
741    // Test across rows and groups with a regex
742    // Filter out everything that doesn't match "*-2"
743    // Expect all keys in two rows
744    f = new RowFilter(CompareOperator.EQUAL, new RegexStringComparator(".+-2"));
745    s = new Scan();
746    s.setFilter(f);
747
748    kvs = new KeyValue[] {
749      // testRowOne-2
750      new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
751      new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
752      new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
753      new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
754      new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
755      new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
756      // testRowTwo-2
757      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
758      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
759      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
760      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
761      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
762      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]) };
763    verifyScanFull(s, kvs);
764  }
765
766  @Test
767  public void testValueFilter() throws Exception {
768    // Match group one rows
769    long expectedRows = numRows / 2;
770    long expectedKeys = colsPerRow;
771    Filter f =
772      new ValueFilter(CompareOperator.EQUAL, new BinaryComparator(Bytes.toBytes("testValueOne")));
773    Scan s = new Scan();
774    s.setFilter(f);
775    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
776
777    // Match group two rows
778    expectedRows = numRows / 2;
779    expectedKeys = colsPerRow;
780    f = new ValueFilter(CompareOperator.EQUAL, new BinaryComparator(Bytes.toBytes("testValueTwo")));
781    s = new Scan();
782    s.setFilter(f);
783    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
784
785    // Match all values using regex
786    expectedRows = numRows;
787    expectedKeys = colsPerRow;
788    f = new ValueFilter(CompareOperator.EQUAL, new RegexStringComparator("testValue((One)|(Two))"));
789    s = new Scan();
790    s.setFilter(f);
791    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
792
793    // Match values less than
794    // Expect group one rows
795    expectedRows = numRows / 2;
796    expectedKeys = colsPerRow;
797    f = new ValueFilter(CompareOperator.LESS, new BinaryComparator(Bytes.toBytes("testValueTwo")));
798    s = new Scan();
799    s.setFilter(f);
800    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
801
802    // Match values less than or equal
803    // Expect all rows
804    expectedRows = numRows;
805    expectedKeys = colsPerRow;
806    f = new ValueFilter(CompareOperator.LESS_OR_EQUAL,
807      new BinaryComparator(Bytes.toBytes("testValueTwo")));
808    s = new Scan();
809    s.setFilter(f);
810    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
811
812    // Match values less than or equal
813    // Expect group one rows
814    expectedRows = numRows / 2;
815    expectedKeys = colsPerRow;
816    f = new ValueFilter(CompareOperator.LESS_OR_EQUAL,
817      new BinaryComparator(Bytes.toBytes("testValueOne")));
818    s = new Scan();
819    s.setFilter(f);
820    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
821
822    // Match values not equal
823    // Expect half the rows
824    expectedRows = numRows / 2;
825    expectedKeys = colsPerRow;
826    f = new ValueFilter(CompareOperator.NOT_EQUAL,
827      new BinaryComparator(Bytes.toBytes("testValueOne")));
828    s = new Scan();
829    s.setFilter(f);
830    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
831
832    // Match values greater or equal
833    // Expect all rows
834    expectedRows = numRows;
835    expectedKeys = colsPerRow;
836    f = new ValueFilter(CompareOperator.GREATER_OR_EQUAL,
837      new BinaryComparator(Bytes.toBytes("testValueOne")));
838    s = new Scan();
839    s.setFilter(f);
840    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
841
842    // Match values greater
843    // Expect half rows
844    expectedRows = numRows / 2;
845    expectedKeys = colsPerRow;
846    f =
847      new ValueFilter(CompareOperator.GREATER, new BinaryComparator(Bytes.toBytes("testValueOne")));
848    s = new Scan();
849    s.setFilter(f);
850    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
851
852    // Match values not equal to testValueOne
853    // Look across rows and fully validate the keys and ordering
854    // Should see all keys in all group two rows
855    f = new ValueFilter(CompareOperator.NOT_EQUAL,
856      new BinaryComparator(Bytes.toBytes("testValueOne")));
857    s = new Scan();
858    s.setFilter(f);
859
860    KeyValue[] kvs = {
861      // testRowTwo-0
862      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
863      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
864      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
865      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
866      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
867      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
868      // testRowTwo-2
869      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
870      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
871      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
872      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
873      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
874      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
875      // testRowTwo-3
876      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
877      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
878      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
879      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
880      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
881      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]), };
882    verifyScanFull(s, kvs);
883  }
884
885  @Test
886  public void testSkipFilter() throws Exception {
887    // Test for qualifier regex: "testQualifierOne-2"
888    // Should only get rows from second group, and all keys
889    Filter f = new SkipFilter(new QualifierFilter(CompareOperator.NOT_EQUAL,
890      new BinaryComparator(Bytes.toBytes("testQualifierOne-2"))));
891    Scan s = new Scan();
892    s.setFilter(f);
893
894    KeyValue[] kvs = {
895      // testRowTwo-0
896      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
897      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
898      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
899      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
900      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
901      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
902      // testRowTwo-2
903      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
904      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
905      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
906      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
907      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
908      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
909      // testRowTwo-3
910      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
911      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
912      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
913      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
914      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
915      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]), };
916    verifyScanFull(s, kvs);
917  }
918
919  @Test
920  public void testFilterList() throws Exception {
921    // Test getting a single row, single key using Row, Qualifier, and Value
922    // regular expression and substring filters
923    // Use must pass all
924    List<Filter> filters = new ArrayList<>(3);
925    filters.add(new RowFilter(CompareOperator.EQUAL, new RegexStringComparator(".+-2")));
926    filters.add(new QualifierFilter(CompareOperator.EQUAL, new RegexStringComparator(".+-2")));
927    filters.add(new ValueFilter(CompareOperator.EQUAL, new SubstringComparator("One")));
928    Filter f = new FilterList(Operator.MUST_PASS_ALL, filters);
929    Scan s = new Scan();
930    s.addFamily(FAMILIES[0]);
931    s.setFilter(f);
932    KeyValue[] kvs = { new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]) };
933    verifyScanFull(s, kvs);
934
935    // Test getting everything with a MUST_PASS_ONE filter including row, qf,
936    // val, regular expression and substring filters
937    filters.clear();
938    filters.add(new RowFilter(CompareOperator.EQUAL, new RegexStringComparator(".+Two.+")));
939    filters.add(new QualifierFilter(CompareOperator.EQUAL, new RegexStringComparator(".+-2")));
940    filters.add(new ValueFilter(CompareOperator.EQUAL, new SubstringComparator("One")));
941    f = new FilterList(Operator.MUST_PASS_ONE, filters);
942    s = new Scan();
943    s.setFilter(f);
944    verifyScanNoEarlyOut(s, numRows, colsPerRow);
945  }
946
947  @Test
948  public void testFirstKeyOnlyFilter() throws Exception {
949    Scan s = new Scan();
950    s.setFilter(new FirstKeyOnlyFilter());
951    // Expected KVs, the first KV from each of the remaining 6 rows
952    KeyValue[] kvs = { new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
953      new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
954      new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
955      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
956      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
957      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]) };
958    verifyScanFull(s, kvs);
959  }
960}