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.filter;
19 
20 import static org.junit.Assert.assertEquals;
21 
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.List;
26 
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.hbase.Cell;
30 import org.apache.hadoop.hbase.HBaseTestingUtility;
31 import org.apache.hadoop.hbase.client.HTable;
32 import org.apache.hadoop.hbase.client.Put;
33 import org.apache.hadoop.hbase.client.Result;
34 import org.apache.hadoop.hbase.client.ResultScanner;
35 import org.apache.hadoop.hbase.client.Scan;
36 import org.apache.hadoop.hbase.filter.MultiRowRangeFilter.RowRange;
37 import org.apache.hadoop.hbase.testclassification.MediumTests;
38 import org.apache.hadoop.hbase.util.Bytes;
39 import org.junit.AfterClass;
40 import org.junit.Assert;
41 import org.junit.BeforeClass;
42 import org.junit.Test;
43 import org.junit.experimental.categories.Category;
44 
45 @Category(MediumTests.class)
46 public class TestMultiRowRangeFilter {
47 
48   private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
49   private static final Log LOG = LogFactory.getLog(TestMultiRowRangeFilter.class);
50   private byte[] family = Bytes.toBytes("family");
51   private byte[] qf = Bytes.toBytes("qf");
52   private byte[] value = Bytes.toBytes("val");
53   private byte[] tableName;
54   private int numRows = 100;
55 
56   /**
57    * @throws Exception
58    */
59   @BeforeClass
setUpBeforeClass()60   public static void setUpBeforeClass() throws Exception {
61     TEST_UTIL.startMiniCluster();
62   }
63 
64   /**
65    * @throws Exception
66    */
67   @AfterClass
tearDownAfterClass()68   public static void tearDownAfterClass() throws Exception {
69     TEST_UTIL.shutdownMiniCluster();
70   }
71 
72   @Test
testRanges()73   public void testRanges() throws IOException {
74     byte[] key1Start = new byte[] {-3};
75     byte[] key1End  = new byte[] {-2};
76 
77     byte[] key2Start = new byte[] {5};
78     byte[] key2End  = new byte[] {6};
79 
80     byte[] badKey = new byte[] {-10};
81 
82     MultiRowRangeFilter filter = new MultiRowRangeFilter(Arrays.asList(
83       new MultiRowRangeFilter.RowRange(key1Start, true, key1End, false),
84       new MultiRowRangeFilter.RowRange(key2Start, true, key2End, false)
85         ));
86     filter.filterRowKey(badKey, 0, 1);
87     assertEquals(Filter.ReturnCode.SEEK_NEXT_USING_HINT, filter.filterKeyValue(null));
88   }
89 
90   @Test
testOutOfOrderScannerNextException()91   public void testOutOfOrderScannerNextException() throws Exception {
92     MultiRowRangeFilter filter = new MultiRowRangeFilter(Arrays.asList(
93             new MultiRowRangeFilter.RowRange(Bytes.toBytes("b"), true, Bytes.toBytes("c"), true),
94             new MultiRowRangeFilter.RowRange(Bytes.toBytes("d"), true, Bytes.toBytes("e"), true)
95     ));
96     filter.filterRowKey(Bytes.toBytes("a"), 0, 1);
97     assertEquals(Filter.ReturnCode.SEEK_NEXT_USING_HINT, filter.filterKeyValue(null));
98     filter.filterRowKey(Bytes.toBytes("b"), 0, 1);
99     assertEquals(Filter.ReturnCode.INCLUDE, filter.filterKeyValue(null));
100     filter.filterRowKey(Bytes.toBytes("c"), 0, 1);
101     assertEquals(Filter.ReturnCode.INCLUDE, filter.filterKeyValue(null));
102     filter.filterRowKey(Bytes.toBytes("d"), 0, 1);
103     assertEquals(Filter.ReturnCode.INCLUDE, filter.filterKeyValue(null));
104     filter.filterRowKey(Bytes.toBytes("e"), 0, 1);
105     assertEquals(Filter.ReturnCode.INCLUDE, filter.filterKeyValue(null));
106   }
107 
108   @Test
testMergeAndSortWithEmptyStartRow()109   public void testMergeAndSortWithEmptyStartRow() throws IOException {
110     List<RowRange> ranges = new ArrayList<RowRange>();
111     ranges.add(new RowRange(Bytes.toBytes(""), true, Bytes.toBytes(20), false));
112     ranges.add(new RowRange(Bytes.toBytes(15), true, Bytes.toBytes(40), false));
113     List<RowRange> actualRanges = MultiRowRangeFilter.sortAndMerge(ranges);
114     List<RowRange> expectedRanges = new ArrayList<RowRange>();
115     expectedRanges.add(new RowRange(Bytes.toBytes(""), true, Bytes.toBytes(40), false));
116     assertRangesEqual(expectedRanges, actualRanges);
117   }
118 
119   @Test
testMergeAndSortWithEmptyStopRow()120   public void testMergeAndSortWithEmptyStopRow() throws IOException {
121     List<RowRange> ranges = new ArrayList<RowRange>();
122     ranges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
123     ranges.add(new RowRange(Bytes.toBytes(15), true, Bytes.toBytes(""), false));
124     ranges.add(new RowRange(Bytes.toBytes(30), true, Bytes.toBytes(70), false));
125     List<RowRange> actualRanges = MultiRowRangeFilter.sortAndMerge(ranges);
126     List<RowRange> expectedRanges = new ArrayList<RowRange>();
127     expectedRanges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(""), false));
128     assertRangesEqual(expectedRanges, actualRanges);
129   }
130 
131   @Test
testMergeAndSortWithEmptyStartRowAndStopRow()132   public void testMergeAndSortWithEmptyStartRowAndStopRow() throws IOException {
133     List<RowRange> ranges = new ArrayList<RowRange>();
134     ranges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
135     ranges.add(new RowRange(Bytes.toBytes(""), true, Bytes.toBytes(""), false));
136     ranges.add(new RowRange(Bytes.toBytes(30), true, Bytes.toBytes(70), false));
137     List<RowRange> actualRanges = MultiRowRangeFilter.sortAndMerge(ranges);
138     List<RowRange> expectedRanges = new ArrayList<RowRange>();
139     expectedRanges.add(new RowRange(Bytes.toBytes(""), true, Bytes.toBytes(""), false));
140     assertRangesEqual(expectedRanges, actualRanges);
141   }
142 
143   @Test(expected=IllegalArgumentException.class)
testMultiRowRangeWithoutRange()144   public void testMultiRowRangeWithoutRange() throws IOException {
145     List<RowRange> ranges = new ArrayList<RowRange>();
146     new MultiRowRangeFilter(ranges);
147   }
148 
149   @Test(expected=IllegalArgumentException.class)
testMultiRowRangeWithInvalidRange()150   public void testMultiRowRangeWithInvalidRange() throws IOException {
151     List<RowRange> ranges = new ArrayList<RowRange>();
152     ranges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
153     // the start row larger than the stop row
154     ranges.add(new RowRange(Bytes.toBytes(80), true, Bytes.toBytes(20), false));
155     ranges.add(new RowRange(Bytes.toBytes(30), true, Bytes.toBytes(70), false));
156     new MultiRowRangeFilter(ranges);
157   }
158 
159   @Test
testMergeAndSortWithoutOverlap()160   public void testMergeAndSortWithoutOverlap() throws IOException {
161     List<RowRange> ranges = new ArrayList<RowRange>();
162     ranges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
163     ranges.add(new RowRange(Bytes.toBytes(30), true, Bytes.toBytes(40), false));
164     ranges.add(new RowRange(Bytes.toBytes(60), true, Bytes.toBytes(70), false));
165     List<RowRange> actualRanges = MultiRowRangeFilter.sortAndMerge(ranges);
166     List<RowRange> expectedRanges = new ArrayList<RowRange>();
167     expectedRanges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
168     expectedRanges.add(new RowRange(Bytes.toBytes(30), true, Bytes.toBytes(40), false));
169     expectedRanges.add(new RowRange(Bytes.toBytes(60), true, Bytes.toBytes(70), false));
170     assertRangesEqual(expectedRanges, actualRanges);
171   }
172 
173   @Test
testMergeAndSortWithOverlap()174   public void testMergeAndSortWithOverlap() throws IOException {
175     List<RowRange> ranges = new ArrayList<RowRange>();
176     ranges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
177     ranges.add(new RowRange(Bytes.toBytes(15), true, Bytes.toBytes(40), false));
178     ranges.add(new RowRange(Bytes.toBytes(20), true, Bytes.toBytes(30), false));
179     ranges.add(new RowRange(Bytes.toBytes(30), true, Bytes.toBytes(50), false));
180     ranges.add(new RowRange(Bytes.toBytes(30), true, Bytes.toBytes(70), false));
181     ranges.add(new RowRange(Bytes.toBytes(90), true, Bytes.toBytes(100), false));
182     ranges.add(new RowRange(Bytes.toBytes(95), true, Bytes.toBytes(100), false));
183     List<RowRange> actualRanges = MultiRowRangeFilter.sortAndMerge(ranges);
184     List<RowRange> expectedRanges = new ArrayList<RowRange>();
185     expectedRanges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(70), false));
186     expectedRanges.add(new RowRange(Bytes.toBytes(90), true, Bytes.toBytes(100), false));
187     assertRangesEqual(expectedRanges, actualRanges);
188   }
189 
190   @Test
testMergeAndSortWithStartRowInclusive()191   public void testMergeAndSortWithStartRowInclusive() throws IOException {
192     List<RowRange> ranges = new ArrayList<RowRange>();
193     ranges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
194     ranges.add(new RowRange(Bytes.toBytes(20), true, Bytes.toBytes(""), false));
195     List<RowRange> actualRanges = MultiRowRangeFilter.sortAndMerge(ranges);
196     List<RowRange> expectedRanges = new ArrayList<RowRange>();
197     expectedRanges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(""), false));
198     assertRangesEqual(expectedRanges, actualRanges);
199   }
200 
201   @Test
testMergeAndSortWithRowExclusive()202   public void testMergeAndSortWithRowExclusive() throws IOException {
203     List<RowRange> ranges = new ArrayList<RowRange>();
204     ranges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
205     ranges.add(new RowRange(Bytes.toBytes(20), false, Bytes.toBytes(""), false));
206     List<RowRange> actualRanges = MultiRowRangeFilter.sortAndMerge(ranges);
207     List<RowRange> expectedRanges = new ArrayList<RowRange>();
208     expectedRanges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
209     expectedRanges.add(new RowRange(Bytes.toBytes(20), false, Bytes.toBytes(""), false));
210     assertRangesEqual(expectedRanges, actualRanges);
211   }
212 
213   @Test
testMergeAndSortWithRowInclusive()214   public void testMergeAndSortWithRowInclusive() throws IOException {
215     List<RowRange> ranges = new ArrayList<RowRange>();
216     ranges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), true));
217     ranges.add(new RowRange(Bytes.toBytes(20), false, Bytes.toBytes(""), false));
218     List<RowRange> actualRanges = MultiRowRangeFilter.sortAndMerge(ranges);
219     List<RowRange> expectedRanges = new ArrayList<RowRange>();
220     expectedRanges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(""), false));
221     assertRangesEqual(expectedRanges, actualRanges);
222   }
223 
assertRangesEqual(List<RowRange> expected, List<RowRange> actual)224   public void assertRangesEqual(List<RowRange> expected, List<RowRange> actual) {
225     assertEquals(expected.size(), actual.size());
226     for(int i = 0; i < expected.size(); i++) {
227       Assert.assertTrue(Bytes.equals(expected.get(i).getStartRow(), actual.get(i).getStartRow()));
228       Assert.assertTrue(expected.get(i).isStartRowInclusive() ==
229           actual.get(i).isStartRowInclusive());
230       Assert.assertTrue(Bytes.equals(expected.get(i).getStopRow(), actual.get(i).getStopRow()));
231       Assert.assertTrue(expected.get(i).isStopRowInclusive() ==
232           actual.get(i).isStopRowInclusive());
233     }
234   }
235 
236   @Test
testMultiRowRangeFilterWithRangeOverlap()237   public void testMultiRowRangeFilterWithRangeOverlap() throws IOException {
238     tableName = Bytes.toBytes("testMultiRowRangeFilterWithRangeOverlap");
239     HTable ht = TEST_UTIL.createTable(tableName, family, Integer.MAX_VALUE);
240     generateRows(numRows, ht, family, qf, value);
241 
242     Scan scan = new Scan();
243     scan.setMaxVersions();
244 
245     List<RowRange> ranges = new ArrayList<RowRange>();
246     ranges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
247     ranges.add(new RowRange(Bytes.toBytes(15), true, Bytes.toBytes(40), false));
248     ranges.add(new RowRange(Bytes.toBytes(65), true, Bytes.toBytes(75), false));
249     ranges.add(new RowRange(Bytes.toBytes(60), true, null, false));
250     ranges.add(new RowRange(Bytes.toBytes(60), true, Bytes.toBytes(80), false));
251 
252     MultiRowRangeFilter filter = new MultiRowRangeFilter(ranges);
253     scan.setFilter(filter);
254     int resultsSize = getResultsSize(ht, scan);
255     LOG.info("found " + resultsSize + " results");
256     List<Cell> results1 = getScanResult(Bytes.toBytes(10), Bytes.toBytes(40), ht);
257     List<Cell> results2 = getScanResult(Bytes.toBytes(60), Bytes.toBytes(""), ht);
258 
259     assertEquals(results1.size() + results2.size(), resultsSize);
260 
261     ht.close();
262   }
263 
264   @Test
testMultiRowRangeFilterWithoutRangeOverlap()265   public void testMultiRowRangeFilterWithoutRangeOverlap() throws IOException {
266     tableName = Bytes.toBytes("testMultiRowRangeFilterWithoutRangeOverlap");
267     HTable ht = TEST_UTIL.createTable(tableName, family, Integer.MAX_VALUE);
268     generateRows(numRows, ht, family, qf, value);
269 
270     Scan scan = new Scan();
271     scan.setMaxVersions();
272 
273     List<RowRange> ranges = new ArrayList<RowRange>();
274     ranges.add(new RowRange(Bytes.toBytes(30), true, Bytes.toBytes(40), false));
275     ranges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
276     ranges.add(new RowRange(Bytes.toBytes(60), true, Bytes.toBytes(70), false));
277 
278     MultiRowRangeFilter filter = new MultiRowRangeFilter(ranges);
279     scan.setFilter(filter);
280     int resultsSize = getResultsSize(ht, scan);
281     LOG.info("found " + resultsSize + " results");
282     List<Cell> results1 = getScanResult(Bytes.toBytes(10), Bytes.toBytes(20), ht);
283     List<Cell> results2 = getScanResult(Bytes.toBytes(30), Bytes.toBytes(40), ht);
284     List<Cell> results3 = getScanResult(Bytes.toBytes(60), Bytes.toBytes(70), ht);
285 
286     assertEquals(results1.size() + results2.size() + results3.size(), resultsSize);
287 
288     ht.close();
289   }
290 
291   @Test
testMultiRowRangeFilterWithEmptyStartRow()292   public void testMultiRowRangeFilterWithEmptyStartRow() throws IOException {
293     tableName = Bytes.toBytes("testMultiRowRangeFilterWithEmptyStartRow");
294     HTable ht = TEST_UTIL.createTable(tableName, family, Integer.MAX_VALUE);
295     generateRows(numRows, ht, family, qf, value);
296     Scan scan = new Scan();
297     scan.setMaxVersions();
298 
299     List<RowRange> ranges = new ArrayList<RowRange>();
300     ranges.add(new RowRange(Bytes.toBytes(""), true, Bytes.toBytes(10), false));
301     ranges.add(new RowRange(Bytes.toBytes(30), true, Bytes.toBytes(40), false));
302 
303     MultiRowRangeFilter filter = new MultiRowRangeFilter(ranges);
304     scan.setFilter(filter);
305     int resultsSize = getResultsSize(ht, scan);
306     List<Cell> results1 = getScanResult(Bytes.toBytes(""), Bytes.toBytes(10), ht);
307     List<Cell> results2 = getScanResult(Bytes.toBytes(30), Bytes.toBytes(40), ht);
308     assertEquals(results1.size() + results2.size(), resultsSize);
309 
310     ht.close();
311   }
312 
313   @Test
testMultiRowRangeFilterWithEmptyStopRow()314   public void testMultiRowRangeFilterWithEmptyStopRow() throws IOException {
315     tableName = Bytes.toBytes("testMultiRowRangeFilterWithEmptyStopRow");
316     HTable ht = TEST_UTIL.createTable(tableName, family, Integer.MAX_VALUE);
317     generateRows(numRows, ht, family, qf, value);
318     Scan scan = new Scan();
319     scan.setMaxVersions();
320 
321     List<RowRange> ranges = new ArrayList<RowRange>();
322     ranges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(""), false));
323     ranges.add(new RowRange(Bytes.toBytes(30), true, Bytes.toBytes(40), false));
324 
325     MultiRowRangeFilter filter = new MultiRowRangeFilter(ranges);
326     scan.setFilter(filter);
327     int resultsSize = getResultsSize(ht, scan);
328     List<Cell> results1 = getScanResult(Bytes.toBytes(10), Bytes.toBytes(""), ht);
329     assertEquals(results1.size(), resultsSize);
330 
331     ht.close();
332   }
333 
334   @Test
testMultiRowRangeFilterWithInclusive()335   public void testMultiRowRangeFilterWithInclusive() throws IOException {
336     tableName = Bytes.toBytes("testMultiRowRangeFilterWithInclusive");
337     HTable ht = TEST_UTIL.createTable(tableName, family, Integer.MAX_VALUE);
338     generateRows(numRows, ht, family, qf, value);
339 
340     Scan scan = new Scan();
341     scan.setMaxVersions();
342 
343     List<RowRange> ranges = new ArrayList<RowRange>();
344     ranges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
345     ranges.add(new RowRange(Bytes.toBytes(20), true, Bytes.toBytes(40), false));
346     ranges.add(new RowRange(Bytes.toBytes(65), true, Bytes.toBytes(75), false));
347     ranges.add(new RowRange(Bytes.toBytes(60), true, null, false));
348     ranges.add(new RowRange(Bytes.toBytes(60), true, Bytes.toBytes(80), false));
349 
350     MultiRowRangeFilter filter = new MultiRowRangeFilter(ranges);
351     scan.setFilter(filter);
352     int resultsSize = getResultsSize(ht, scan);
353     LOG.info("found " + resultsSize + " results");
354     List<Cell> results1 = getScanResult(Bytes.toBytes(10), Bytes.toBytes(40), ht);
355     List<Cell> results2 = getScanResult(Bytes.toBytes(60), Bytes.toBytes(""), ht);
356 
357     assertEquals(results1.size() + results2.size(), resultsSize);
358 
359     ht.close();
360   }
361 
362   @Test
testMultiRowRangeFilterWithExclusive()363   public void testMultiRowRangeFilterWithExclusive() throws IOException {
364     tableName = Bytes.toBytes("testMultiRowRangeFilterWithExclusive");
365     HTable ht = TEST_UTIL.createTable(tableName, family, Integer.MAX_VALUE);
366     generateRows(numRows, ht, family, qf, value);
367 
368     Scan scan = new Scan();
369     scan.setMaxVersions();
370 
371     List<RowRange> ranges = new ArrayList<RowRange>();
372     ranges.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
373     ranges.add(new RowRange(Bytes.toBytes(20), false, Bytes.toBytes(40), false));
374     ranges.add(new RowRange(Bytes.toBytes(65), true, Bytes.toBytes(75), false));
375 
376     MultiRowRangeFilter filter = new MultiRowRangeFilter(ranges);
377     scan.setFilter(filter);
378     int resultsSize = getResultsSize(ht, scan);
379     LOG.info("found " + resultsSize + " results");
380     List<Cell> results1 = getScanResult(Bytes.toBytes(10), Bytes.toBytes(40), ht);
381     List<Cell> results2 = getScanResult(Bytes.toBytes(65), Bytes.toBytes(75), ht);
382 
383     assertEquals((results1.size() - 1) + results2.size(), resultsSize);
384 
385     ht.close();
386   }
387 
388   @Test
testMultiRowRangeWithFilterListAndOperator()389   public void testMultiRowRangeWithFilterListAndOperator() throws IOException {
390     tableName = Bytes.toBytes("TestMultiRowRangeFilterWithFilterListAndOperator");
391     HTable ht = TEST_UTIL.createTable(tableName, family, Integer.MAX_VALUE);
392     generateRows(numRows, ht, family, qf, value);
393 
394     Scan scan = new Scan();
395     scan.setMaxVersions();
396 
397     List<RowRange> ranges1 = new ArrayList<RowRange>();
398     ranges1.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
399     ranges1.add(new RowRange(Bytes.toBytes(30), true, Bytes.toBytes(40), false));
400     ranges1.add(new RowRange(Bytes.toBytes(60), true, Bytes.toBytes(70), false));
401 
402     MultiRowRangeFilter filter1 = new MultiRowRangeFilter(ranges1);
403 
404     List<RowRange> ranges2 = new ArrayList<RowRange>();
405     ranges2.add(new RowRange(Bytes.toBytes(20), true, Bytes.toBytes(40), false));
406     ranges2.add(new RowRange(Bytes.toBytes(80), true, Bytes.toBytes(90), false));
407 
408     MultiRowRangeFilter filter2 = new MultiRowRangeFilter(ranges2);
409 
410     FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
411     filterList.addFilter(filter1);
412     filterList.addFilter(filter2);
413     scan.setFilter(filterList);
414     int resultsSize = getResultsSize(ht, scan);
415     LOG.info("found " + resultsSize + " results");
416     List<Cell> results1 = getScanResult(Bytes.toBytes(30), Bytes.toBytes(40), ht);
417 
418     assertEquals(results1.size(), resultsSize);
419 
420     ht.close();
421   }
422 
423   @Test
testMultiRowRangeWithFilterListOrOperator()424   public void testMultiRowRangeWithFilterListOrOperator() throws IOException {
425     tableName = Bytes.toBytes("TestMultiRowRangeFilterWithFilterListOrOperator");
426     HTable ht = TEST_UTIL.createTable(tableName, family, Integer.MAX_VALUE);
427     generateRows(numRows, ht, family, qf, value);
428 
429     Scan scan = new Scan();
430     scan.setMaxVersions();
431 
432     List<RowRange> ranges1 = new ArrayList<RowRange>();
433     ranges1.add(new RowRange(Bytes.toBytes(30), true, Bytes.toBytes(40), false));
434     ranges1.add(new RowRange(Bytes.toBytes(10), true, Bytes.toBytes(20), false));
435     ranges1.add(new RowRange(Bytes.toBytes(60), true, Bytes.toBytes(70), false));
436 
437     MultiRowRangeFilter filter1 = new MultiRowRangeFilter(ranges1);
438 
439     List<RowRange> ranges2 = new ArrayList<RowRange>();
440     ranges2.add(new RowRange(Bytes.toBytes(20), true, Bytes.toBytes(40), false));
441     ranges2.add(new RowRange(Bytes.toBytes(80), true, Bytes.toBytes(90), false));
442 
443     MultiRowRangeFilter filter2 = new MultiRowRangeFilter(ranges2);
444 
445     FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ONE);
446     filterList.addFilter(filter1);
447     filterList.addFilter(filter2);
448     scan.setFilter(filterList);
449     int resultsSize = getResultsSize(ht, scan);
450     LOG.info("found " + resultsSize + " results");
451     List<Cell> results1 = getScanResult(Bytes.toBytes(10), Bytes.toBytes(40), ht);
452     List<Cell> results2 = getScanResult(Bytes.toBytes(60), Bytes.toBytes(70), ht);
453     List<Cell> results3 = getScanResult(Bytes.toBytes(80), Bytes.toBytes(90), ht);
454 
455     assertEquals(results1.size() + results2.size() + results3.size(),resultsSize);
456 
457     ht.close();
458   }
459 
generateRows(int numberOfRows, HTable ht, byte[] family, byte[] qf, byte[] value)460   private void generateRows(int numberOfRows, HTable ht, byte[] family, byte[] qf, byte[] value)
461       throws IOException {
462     for (int i = 0; i < numberOfRows; i++) {
463       byte[] row = Bytes.toBytes(i);
464       Put p = new Put(row);
465       p.add(family, qf, value);
466       ht.put(p);
467     }
468     TEST_UTIL.flush();
469   }
470 
getScanResult(byte[] startRow, byte[] stopRow, HTable ht)471   private List<Cell> getScanResult(byte[] startRow, byte[] stopRow, HTable ht) throws IOException {
472     Scan scan = new Scan();
473     scan.setMaxVersions();
474     if(!Bytes.toString(startRow).isEmpty()) {
475       scan.setStartRow(startRow);
476     }
477     if(!Bytes.toString(stopRow).isEmpty()) {
478       scan.setStopRow(stopRow);
479     }
480     ResultScanner scanner = ht.getScanner(scan);
481     List<Cell> kvList = new ArrayList<Cell>();
482     Result r;
483     while ((r = scanner.next()) != null) {
484       for (Cell kv : r.listCells()) {
485         kvList.add(kv);
486       }
487     }
488     return kvList;
489   }
490 
getResultsSize(HTable ht, Scan scan)491   private int getResultsSize(HTable ht, Scan scan) throws IOException {
492     ResultScanner scanner = ht.getScanner(scan);
493     List<Cell> results = new ArrayList<Cell>();
494     Result r;
495     while ((r = scanner.next()) != null) {
496       for (Cell kv : r.listCells()) {
497         results.add(kv);
498       }
499     }
500     return results.size();
501   }
502 }
503