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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package org
.apache
.hadoop
.hbase
.client
;
20 import static org
.junit
.Assert
.assertEquals
;
21 import static org
.junit
.Assert
.assertFalse
;
22 import static org
.junit
.Assert
.assertTrue
;
24 import java
.io
.IOException
;
25 import java
.util
.ArrayList
;
26 import java
.util
.List
;
27 import org
.apache
.hadoop
.hbase
.HBaseClassTestRule
;
28 import org
.apache
.hadoop
.hbase
.HBaseTestingUtility
;
29 import org
.apache
.hadoop
.hbase
.TableName
;
30 import org
.apache
.hadoop
.hbase
.testclassification
.ClientTests
;
31 import org
.apache
.hadoop
.hbase
.testclassification
.MediumTests
;
32 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
33 import org
.junit
.AfterClass
;
34 import org
.junit
.BeforeClass
;
35 import org
.junit
.ClassRule
;
36 import org
.junit
.Test
;
37 import org
.junit
.experimental
.categories
.Category
;
38 import org
.junit
.runner
.RunWith
;
39 import org
.junit
.runners
.Parameterized
;
40 import org
.junit
.runners
.Parameterized
.Parameter
;
41 import org
.junit
.runners
.Parameterized
.Parameters
;
44 * Testcase for newly added feature in HBASE-17143, such as startRow and stopRow
45 * inclusive/exclusive, limit for rows, etc.
47 @RunWith(Parameterized
.class)
48 @Category({ MediumTests
.class, ClientTests
.class })
49 public class TestScannersFromClientSide2
{
52 public static final HBaseClassTestRule CLASS_RULE
=
53 HBaseClassTestRule
.forClass(TestScannersFromClientSide2
.class);
55 private static final HBaseTestingUtility TEST_UTIL
= new HBaseTestingUtility();
57 private static TableName TABLE_NAME
= TableName
.valueOf("scan");
59 private static byte[] FAMILY
= Bytes
.toBytes("cf");
61 private static byte[] CQ1
= Bytes
.toBytes("cq1");
63 private static byte[] CQ2
= Bytes
.toBytes("cq2");
69 public boolean smallResultSize
;
72 public boolean allowPartial
;
74 @Parameters(name
= "{index}: batch={0}, smallResultSize={1}, allowPartial={2}")
75 public static List
<Object
[]> params() {
76 List
<Object
[]> params
= new ArrayList
<>();
77 boolean[] values
= new boolean[] { false, true };
78 for (int i
= 0; i
< 2; i
++) {
79 for (int j
= 0; j
< 2; j
++) {
80 for (int k
= 0; k
< 2; k
++) {
81 params
.add(new Object
[] { values
[i
], values
[j
], values
[k
] });
89 public static void setUp() throws Exception
{
90 TEST_UTIL
.startMiniCluster(3);
91 byte[][] splitKeys
= new byte[8][];
92 for (int i
= 111; i
< 999; i
+= 111) {
93 splitKeys
[i
/ 111 - 1] = Bytes
.toBytes(String
.format("%03d", i
));
95 Table table
= TEST_UTIL
.createTable(TABLE_NAME
, FAMILY
, splitKeys
);
96 List
<Put
> puts
= new ArrayList
<>();
97 for (int i
= 0; i
< 1000; i
++) {
98 puts
.add(new Put(Bytes
.toBytes(String
.format("%03d", i
)))
99 .addColumn(FAMILY
, CQ1
, Bytes
.toBytes(i
)).addColumn(FAMILY
, CQ2
, Bytes
.toBytes(i
* i
)));
101 TEST_UTIL
.waitTableAvailable(TABLE_NAME
);
106 public static void tearDown() throws Exception
{
107 TEST_UTIL
.shutdownMiniCluster();
110 private Scan
createScan() {
111 Scan scan
= new Scan();
115 if (smallResultSize
) {
116 scan
.setMaxResultSize(1);
119 scan
.setAllowPartialResults(true);
124 private void assertResultEquals(Result result
, int i
) {
125 assertEquals(String
.format("%03d", i
), Bytes
.toString(result
.getRow()));
126 assertEquals(i
, Bytes
.toInt(result
.getValue(FAMILY
, CQ1
)));
127 assertEquals(i
* i
, Bytes
.toInt(result
.getValue(FAMILY
, CQ2
)));
130 private List
<Result
> doScan(Scan scan
) throws IOException
{
131 List
<Result
> results
= new ArrayList
<>();
132 try (Table table
= TEST_UTIL
.getConnection().getTable(TABLE_NAME
);
133 ResultScanner scanner
= table
.getScanner(scan
)) {
134 for (Result r
; (r
= scanner
.next()) != null;) {
138 return assertAndCreateCompleteResults(results
);
141 private List
<Result
> assertAndCreateCompleteResults(List
<Result
> results
) throws IOException
{
142 if ((!batch
&& !allowPartial
) || (allowPartial
&& !batch
&& !smallResultSize
)) {
143 for (Result result
: results
) {
144 assertFalse("Should not have partial result", result
.mayHaveMoreCellsInRow());
148 List
<Result
> completeResults
= new ArrayList
<>();
149 List
<Result
> partialResults
= new ArrayList
<>();
150 for (Result result
: results
) {
151 if (!result
.mayHaveMoreCellsInRow()) {
152 assertFalse("Should have partial result", partialResults
.isEmpty());
153 partialResults
.add(result
);
154 completeResults
.add(Result
.createCompleteResult(partialResults
));
155 partialResults
.clear();
157 partialResults
.add(result
);
160 assertTrue("Should not have orphan partial result", partialResults
.isEmpty());
161 return completeResults
;
164 private void testScan(int start
, boolean startInclusive
, int stop
, boolean stopInclusive
,
165 int limit
) throws Exception
{
167 createScan().withStartRow(Bytes
.toBytes(String
.format("%03d", start
)), startInclusive
)
168 .withStopRow(Bytes
.toBytes(String
.format("%03d", stop
)), stopInclusive
);
170 scan
.setLimit(limit
);
172 List
<Result
> results
= doScan(scan
);
173 int actualStart
= startInclusive ? start
: start
+ 1;
174 int actualStop
= stopInclusive ? stop
+ 1 : stop
;
175 int count
= actualStop
- actualStart
;
177 count
= Math
.min(count
, limit
);
179 assertEquals(count
, results
.size());
180 for (int i
= 0; i
< count
; i
++) {
181 assertResultEquals(results
.get(i
), actualStart
+ i
);
185 private void testReversedScan(int start
, boolean startInclusive
, int stop
, boolean stopInclusive
,
186 int limit
) throws Exception
{
187 Scan scan
= createScan()
188 .withStartRow(Bytes
.toBytes(String
.format("%03d", start
)), startInclusive
)
189 .withStopRow(Bytes
.toBytes(String
.format("%03d", stop
)), stopInclusive
).setReversed(true);
191 scan
.setLimit(limit
);
193 List
<Result
> results
= doScan(scan
);
194 int actualStart
= startInclusive ? start
: start
- 1;
195 int actualStop
= stopInclusive ? stop
- 1 : stop
;
196 int count
= actualStart
- actualStop
;
198 count
= Math
.min(count
, limit
);
200 assertEquals(count
, results
.size());
201 for (int i
= 0; i
< count
; i
++) {
202 assertResultEquals(results
.get(i
), actualStart
- i
);
207 public void testScanWithLimit() throws Exception
{
208 testScan(1, true, 998, false, 900); // from first region to last region
209 testScan(123, true, 345, true, 100);
210 testScan(234, true, 456, false, 100);
211 testScan(345, false, 567, true, 100);
212 testScan(456, false, 678, false, 100);
217 public void testScanWithLimitGreaterThanActualCount() throws Exception
{
218 testScan(1, true, 998, false, 1000); // from first region to last region
219 testScan(123, true, 345, true, 200);
220 testScan(234, true, 456, false, 200);
221 testScan(345, false, 567, true, 200);
222 testScan(456, false, 678, false, 200);
226 public void testReversedScanWithLimit() throws Exception
{
227 testReversedScan(998, true, 1, false, 900); // from last region to first region
228 testReversedScan(543, true, 321, true, 100);
229 testReversedScan(654, true, 432, false, 100);
230 testReversedScan(765, false, 543, true, 100);
231 testReversedScan(876, false, 654, false, 100);
235 public void testReversedScanWithLimitGreaterThanActualCount() throws Exception
{
236 testReversedScan(998, true, 1, false, 1000); // from last region to first region
237 testReversedScan(543, true, 321, true, 200);
238 testReversedScan(654, true, 432, false, 200);
239 testReversedScan(765, false, 543, true, 200);
240 testReversedScan(876, false, 654, false, 200);
244 public void testStartRowStopRowInclusive() throws Exception
{
245 testScan(1, true, 998, false, -1); // from first region to last region
246 testScan(123, true, 345, true, -1);
247 testScan(234, true, 456, false, -1);
248 testScan(345, false, 567, true, -1);
249 testScan(456, false, 678, false, -1);
253 public void testReversedStartRowStopRowInclusive() throws Exception
{
254 testReversedScan(998, true, 1, false, -1); // from last region to first region
255 testReversedScan(543, true, 321, true, -1);
256 testReversedScan(654, true, 432, false, -1);
257 testReversedScan(765, false, 543, true, -1);
258 testReversedScan(876, false, 654, false, -1);