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