View Javadoc

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