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.client;
019
020import static org.apache.hadoop.hbase.HBaseTestingUtil.countRows;
021import static org.junit.Assert.assertEquals;
022import static org.junit.Assert.assertNull;
023import static org.junit.Assert.assertTrue;
024
025import java.io.IOException;
026import java.util.Arrays;
027import java.util.Iterator;
028import java.util.List;
029import org.apache.hadoop.conf.Configuration;
030import org.apache.hadoop.hbase.Cell;
031import org.apache.hadoop.hbase.CellUtil;
032import org.apache.hadoop.hbase.CompareOperator;
033import org.apache.hadoop.hbase.HBaseCommonTestingUtil;
034import org.apache.hadoop.hbase.HBaseTestingUtil;
035import org.apache.hadoop.hbase.HConstants;
036import org.apache.hadoop.hbase.HRegionLocation;
037import org.apache.hadoop.hbase.StartTestingClusterOption;
038import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
039import org.apache.hadoop.hbase.filter.BinaryComparator;
040import org.apache.hadoop.hbase.filter.Filter;
041import org.apache.hadoop.hbase.filter.FilterList;
042import org.apache.hadoop.hbase.filter.PrefixFilter;
043import org.apache.hadoop.hbase.filter.RowFilter;
044import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
045import org.apache.hadoop.hbase.filter.WhileMatchFilter;
046import org.apache.hadoop.hbase.testclassification.ClientTests;
047import org.apache.hadoop.hbase.testclassification.LargeTests;
048import org.apache.hadoop.hbase.util.Bytes;
049import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
050import org.apache.hadoop.hbase.util.NonRepeatedEnvironmentEdge;
051import org.apache.hadoop.hbase.util.TableDescriptorChecker;
052import org.junit.experimental.categories.Category;
053import org.junit.runner.RunWith;
054import org.junit.runners.Parameterized;
055import org.slf4j.Logger;
056import org.slf4j.LoggerFactory;
057
058import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;
059
060/**
061 * Base for TestFromClientSide* classes. Has common defines and utility used by all.
062 */
063@Category({ LargeTests.class, ClientTests.class })
064@SuppressWarnings("deprecation")
065@RunWith(Parameterized.class)
066class FromClientSideBase {
067  private static final Logger LOG = LoggerFactory.getLogger(FromClientSideBase.class);
068  static HBaseTestingUtil TEST_UTIL;
069  static byte[] ROW = Bytes.toBytes("testRow");
070  static byte[] FAMILY = Bytes.toBytes("testFamily");
071  static final byte[] INVALID_FAMILY = Bytes.toBytes("invalidTestFamily");
072  static byte[] QUALIFIER = Bytes.toBytes("testQualifier");
073  static byte[] VALUE = Bytes.toBytes("testValue");
074  static int SLAVES = 1;
075
076  // To keep the child classes happy.
077  FromClientSideBase() {
078  }
079
080  /**
081   * JUnit does not provide an easy way to run a hook after each parameterized run. Without that
082   * there is no easy way to restart the test cluster after each parameterized run. Annotation
083   * BeforeParam does not work either because it runs before parameterization and hence does not
084   * have access to the test parameters (which is weird). This *hack* checks if the current instance
085   * of test cluster configuration has the passed parameterized configs. In such a case, we can just
086   * reuse the cluster for test and do not need to initialize from scratch. While this is a hack, it
087   * saves a ton of time for the full test and de-flakes it.
088   */
089  protected static boolean isSameParameterizedCluster(Class<?> registryImpl, int numHedgedReqs) {
090    if (TEST_UTIL == null) {
091      return false;
092    }
093    Configuration conf = TEST_UTIL.getConfiguration();
094    Class<?> confClass = conf.getClass(HConstants.CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY,
095      ZKConnectionRegistry.class);
096    int hedgedReqConfig = conf.getInt(MasterRegistry.MASTER_REGISTRY_HEDGED_REQS_FANOUT_KEY,
097      AbstractRpcBasedConnectionRegistry.HEDGED_REQS_FANOUT_DEFAULT);
098    return confClass.getName().equals(registryImpl.getName()) && numHedgedReqs == hedgedReqConfig;
099  }
100
101  protected static final void initialize(Class<? extends ConnectionRegistry> registryImpl,
102    int numHedgedReqs, Class<?>... cps) throws Exception {
103    // initialize() is called for every unit test, however we only want to reset the cluster state
104    // at the end of every parameterized run.
105    if (isSameParameterizedCluster(registryImpl, numHedgedReqs)) {
106      return;
107    }
108    // Uncomment the following lines if more verbosity is needed for
109    // debugging (see HBASE-12285 for details).
110    // ((Log4JLogger)RpcServer.LOG).getLogger().setLevel(Level.ALL);
111    // ((Log4JLogger)RpcClient.LOG).getLogger().setLevel(Level.ALL);
112    // ((Log4JLogger)ScannerCallable.LOG).getLogger().setLevel(Level.ALL);
113    // make sure that we do not get the same ts twice, see HBASE-19731 for more details.
114    EnvironmentEdgeManager.injectEdge(new NonRepeatedEnvironmentEdge());
115    if (TEST_UTIL != null) {
116      // We reached end of a parameterized run, clean up.
117      TEST_UTIL.shutdownMiniCluster();
118    }
119    TEST_UTIL = new HBaseTestingUtil();
120    Configuration conf = TEST_UTIL.getConfiguration();
121    conf.setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
122      Arrays.stream(cps).map(Class::getName).toArray(String[]::new));
123    conf.setBoolean(TableDescriptorChecker.TABLE_SANITY_CHECKS, true); // enable for below tests
124    conf.setClass(HConstants.CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY, registryImpl,
125      ConnectionRegistry.class);
126    Preconditions.checkArgument(numHedgedReqs > 0);
127    conf.setInt(MasterRegistry.MASTER_REGISTRY_HEDGED_REQS_FANOUT_KEY, numHedgedReqs);
128    StartTestingClusterOption.Builder builder = StartTestingClusterOption.builder();
129    // Multiple masters needed only when hedged reads for master registry are enabled.
130    builder.numMasters(numHedgedReqs > 1 ? 3 : 1).numRegionServers(SLAVES);
131    TEST_UTIL.startMiniCluster(builder.build());
132  }
133
134  protected static void afterClass() throws Exception {
135    if (TEST_UTIL != null) {
136      TEST_UTIL.shutdownMiniCluster();
137    }
138  }
139
140  protected void deleteColumns(Table ht, String value, String keyPrefix) throws IOException {
141    ResultScanner scanner = buildScanner(keyPrefix, value, ht);
142    Iterator<Result> it = scanner.iterator();
143    int count = 0;
144    while (it.hasNext()) {
145      Result result = it.next();
146      Delete delete = new Delete(result.getRow());
147      delete.addColumn(Bytes.toBytes("trans-tags"), Bytes.toBytes("qual2"));
148      ht.delete(delete);
149      count++;
150    }
151    assertEquals("Did not perform correct number of deletes", 3, count);
152  }
153
154  protected int getNumberOfRows(String keyPrefix, String value, Table ht) throws Exception {
155    ResultScanner resultScanner = buildScanner(keyPrefix, value, ht);
156    Iterator<Result> scanner = resultScanner.iterator();
157    int numberOfResults = 0;
158    while (scanner.hasNext()) {
159      Result result = scanner.next();
160      System.out.println("Got back key: " + Bytes.toString(result.getRow()));
161      for (Cell kv : result.rawCells()) {
162        System.out.println("kv=" + kv.toString() + ", " + Bytes.toString(CellUtil.cloneValue(kv)));
163      }
164      numberOfResults++;
165    }
166    return numberOfResults;
167  }
168
169  protected ResultScanner buildScanner(String keyPrefix, String value, Table ht)
170    throws IOException {
171    // OurFilterList allFilters = new OurFilterList();
172    FilterList allFilters = new FilterList(/* FilterList.Operator.MUST_PASS_ALL */);
173    allFilters.addFilter(new PrefixFilter(Bytes.toBytes(keyPrefix)));
174    SingleColumnValueFilter filter = new SingleColumnValueFilter(Bytes.toBytes("trans-tags"),
175      Bytes.toBytes("qual2"), CompareOperator.EQUAL, Bytes.toBytes(value));
176    filter.setFilterIfMissing(true);
177    allFilters.addFilter(filter);
178
179    // allFilters.addFilter(new
180    // RowExcludingSingleColumnValueFilter(Bytes.toBytes("trans-tags"),
181    // Bytes.toBytes("qual2"), CompareOp.EQUAL, Bytes.toBytes(value)));
182
183    Scan scan = new Scan();
184    scan.addFamily(Bytes.toBytes("trans-blob"));
185    scan.addFamily(Bytes.toBytes("trans-type"));
186    scan.addFamily(Bytes.toBytes("trans-date"));
187    scan.addFamily(Bytes.toBytes("trans-tags"));
188    scan.addFamily(Bytes.toBytes("trans-group"));
189    scan.setFilter(allFilters);
190
191    return ht.getScanner(scan);
192  }
193
194  protected void putRows(Table ht, int numRows, String value, String key) throws IOException {
195    for (int i = 0; i < numRows; i++) {
196      String row = key + "_" + HBaseCommonTestingUtil.getRandomUUID().toString();
197      System.out.println(String.format("Saving row: %s, with value %s", row, value));
198      Put put = new Put(Bytes.toBytes(row));
199      put.setDurability(Durability.SKIP_WAL);
200      put.addColumn(Bytes.toBytes("trans-blob"), null, Bytes.toBytes("value for blob"));
201      put.addColumn(Bytes.toBytes("trans-type"), null, Bytes.toBytes("statement"));
202      put.addColumn(Bytes.toBytes("trans-date"), null, Bytes.toBytes("20090921010101999"));
203      put.addColumn(Bytes.toBytes("trans-tags"), Bytes.toBytes("qual2"), Bytes.toBytes(value));
204      put.addColumn(Bytes.toBytes("trans-group"), null, Bytes.toBytes("adhocTransactionGroupId"));
205      ht.put(put);
206    }
207  }
208
209  protected void assertRowCount(final Table t, final int expected) throws IOException {
210    assertEquals(expected, countRows(t, new Scan()));
211  }
212
213  /*
214   * @return Scan with RowFilter that does LESS than passed key.
215   */
216  protected Scan createScanWithRowFilter(final byte[] key) {
217    return createScanWithRowFilter(key, null, CompareOperator.LESS);
218  }
219
220  /*
221   * @return Scan with RowFilter that does CompareOp op on passed key.
222   */
223  protected Scan createScanWithRowFilter(final byte[] key, final byte[] startRow,
224    CompareOperator op) {
225    // Make sure key is of some substance... non-null and > than first key.
226    assertTrue(key != null && key.length > 0
227      && Bytes.BYTES_COMPARATOR.compare(key, new byte[] { 'a', 'a', 'a' }) >= 0);
228    LOG.info("Key=" + Bytes.toString(key));
229    Scan s = startRow == null ? new Scan() : new Scan().withStartRow(startRow);
230    Filter f = new RowFilter(op, new BinaryComparator(key));
231    f = new WhileMatchFilter(f);
232    s.setFilter(f);
233    return s;
234  }
235
236  /**
237   * Split table into multiple regions.
238   * @param t Table to split.
239   * @return Map of regions to servers.
240   */
241  protected List<HRegionLocation> splitTable(final Table t) throws IOException {
242    // Split this table in two.
243    Admin admin = TEST_UTIL.getAdmin();
244    admin.split(t.getName());
245    // Is it right closing this admin?
246    admin.close();
247    List<HRegionLocation> regions = waitOnSplit(t);
248    assertTrue(regions.size() > 1);
249    return regions;
250  }
251
252  /*
253   * Wait on table split. May return because we waited long enough on the split and it didn't
254   * happen. Caller should check.
255   * @return Map of table regions; caller needs to check table actually split.
256   */
257  private List<HRegionLocation> waitOnSplit(final Table t) throws IOException {
258    try (RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(t.getName())) {
259      List<HRegionLocation> regions = locator.getAllRegionLocations();
260      int originalCount = regions.size();
261      for (int i = 0; i < TEST_UTIL.getConfiguration().getInt("hbase.test.retries", 30); i++) {
262        try {
263          Thread.sleep(1000);
264        } catch (InterruptedException e) {
265          e.printStackTrace();
266        }
267        regions = locator.getAllRegionLocations();
268        if (regions.size() > originalCount) {
269          break;
270        }
271      }
272      return regions;
273    }
274  }
275
276  protected Result getSingleScanResult(Table ht, Scan scan) throws IOException {
277    ResultScanner scanner = ht.getScanner(scan);
278    Result result = scanner.next();
279    scanner.close();
280    return result;
281  }
282
283  byte[][] makeNAscii(byte[] base, int n) {
284    if (n > 256) {
285      return makeNBig(base, n);
286    }
287    byte[][] ret = new byte[n][];
288    for (int i = 0; i < n; i++) {
289      byte[] tail = Bytes.toBytes(Integer.toString(i));
290      ret[i] = Bytes.add(base, tail);
291    }
292    return ret;
293  }
294
295  protected byte[][] makeN(byte[] base, int n) {
296    if (n > 256) {
297      return makeNBig(base, n);
298    }
299    byte[][] ret = new byte[n][];
300    for (int i = 0; i < n; i++) {
301      ret[i] = Bytes.add(base, new byte[] { (byte) i });
302    }
303    return ret;
304  }
305
306  protected byte[][] makeNBig(byte[] base, int n) {
307    byte[][] ret = new byte[n][];
308    for (int i = 0; i < n; i++) {
309      int byteA = (i % 256);
310      int byteB = (i >> 8);
311      ret[i] = Bytes.add(base, new byte[] { (byte) byteB, (byte) byteA });
312    }
313    return ret;
314  }
315
316  protected long[] makeStamps(int n) {
317    long[] stamps = new long[n];
318    for (int i = 0; i < n; i++) {
319      stamps[i] = i + 1L;
320    }
321    return stamps;
322  }
323
324  protected static boolean equals(byte[] left, byte[] right) {
325    if (left == null && right == null) {
326      return true;
327    }
328    if (left == null && right.length == 0) {
329      return true;
330    }
331    if (right == null && left.length == 0) {
332      return true;
333    }
334    return Bytes.equals(left, right);
335  }
336
337  protected void assertKey(Cell key, byte[] row, byte[] family, byte[] qualifier, byte[] value) {
338    assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
339      + Bytes.toString(CellUtil.cloneRow(key)) + "]", equals(row, CellUtil.cloneRow(key)));
340    assertTrue(
341      "Expected family [" + Bytes.toString(family) + "] " + "Got family ["
342        + Bytes.toString(CellUtil.cloneFamily(key)) + "]",
343      equals(family, CellUtil.cloneFamily(key)));
344    assertTrue(
345      "Expected qualifier [" + Bytes.toString(qualifier) + "] " + "Got qualifier ["
346        + Bytes.toString(CellUtil.cloneQualifier(key)) + "]",
347      equals(qualifier, CellUtil.cloneQualifier(key)));
348    assertTrue("Expected value [" + Bytes.toString(value) + "] " + "Got value ["
349      + Bytes.toString(CellUtil.cloneValue(key)) + "]", equals(value, CellUtil.cloneValue(key)));
350  }
351
352  static void assertIncrementKey(Cell key, byte[] row, byte[] family, byte[] qualifier,
353    long value) {
354    assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
355      + Bytes.toString(CellUtil.cloneRow(key)) + "]", equals(row, CellUtil.cloneRow(key)));
356    assertTrue(
357      "Expected family [" + Bytes.toString(family) + "] " + "Got family ["
358        + Bytes.toString(CellUtil.cloneFamily(key)) + "]",
359      equals(family, CellUtil.cloneFamily(key)));
360    assertTrue(
361      "Expected qualifier [" + Bytes.toString(qualifier) + "] " + "Got qualifier ["
362        + Bytes.toString(CellUtil.cloneQualifier(key)) + "]",
363      equals(qualifier, CellUtil.cloneQualifier(key)));
364    assertEquals("Expected value [" + value + "] " + "Got value ["
365      + Bytes.toLong(CellUtil.cloneValue(key)) + "]", Bytes.toLong(CellUtil.cloneValue(key)),
366      value);
367  }
368
369  protected void assertNumKeys(Result result, int n) throws Exception {
370    assertEquals("Expected " + n + " keys but got " + result.size(), result.size(), n);
371  }
372
373  protected void assertNResult(Result result, byte[] row, byte[][] families, byte[][] qualifiers,
374    byte[][] values, int[][] idxs) {
375    assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
376      + Bytes.toString(result.getRow()) + "]", equals(row, result.getRow()));
377    assertEquals("Expected " + idxs.length + " keys but result contains " + result.size(),
378      result.size(), idxs.length);
379
380    Cell[] keys = result.rawCells();
381
382    for (int i = 0; i < keys.length; i++) {
383      byte[] family = families[idxs[i][0]];
384      byte[] qualifier = qualifiers[idxs[i][1]];
385      byte[] value = values[idxs[i][2]];
386      Cell key = keys[i];
387
388      byte[] famb = CellUtil.cloneFamily(key);
389      byte[] qualb = CellUtil.cloneQualifier(key);
390      byte[] valb = CellUtil.cloneValue(key);
391      assertTrue("(" + i + ") Expected family [" + Bytes.toString(family) + "] " + "Got family ["
392        + Bytes.toString(famb) + "]", equals(family, famb));
393      assertTrue("(" + i + ") Expected qualifier [" + Bytes.toString(qualifier) + "] "
394        + "Got qualifier [" + Bytes.toString(qualb) + "]", equals(qualifier, qualb));
395      assertTrue("(" + i + ") Expected value [" + Bytes.toString(value) + "] " + "Got value ["
396        + Bytes.toString(valb) + "]", equals(value, valb));
397    }
398  }
399
400  protected void assertNResult(Result result, byte[] row, byte[] family, byte[] qualifier,
401    long[] stamps, byte[][] values, int start, int end) {
402    assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
403      + Bytes.toString(result.getRow()) + "]", equals(row, result.getRow()));
404    int expectedResults = end - start + 1;
405    assertEquals(expectedResults, result.size());
406
407    Cell[] keys = result.rawCells();
408
409    for (int i = 0; i < keys.length; i++) {
410      byte[] value = values[end - i];
411      long ts = stamps[end - i];
412      Cell key = keys[i];
413
414      assertTrue("(" + i + ") Expected family [" + Bytes.toString(family) + "] " + "Got family ["
415        + Bytes.toString(CellUtil.cloneFamily(key)) + "]", CellUtil.matchingFamily(key, family));
416      assertTrue(
417        "(" + i + ") Expected qualifier [" + Bytes.toString(qualifier) + "] " + "Got qualifier ["
418          + Bytes.toString(CellUtil.cloneQualifier(key)) + "]",
419        CellUtil.matchingQualifier(key, qualifier));
420      assertEquals("Expected ts [" + ts + "] " + "Got ts [" + key.getTimestamp() + "]", ts,
421        key.getTimestamp());
422      assertTrue("(" + i + ") Expected value [" + Bytes.toString(value) + "] " + "Got value ["
423        + Bytes.toString(CellUtil.cloneValue(key)) + "]", CellUtil.matchingValue(key, value));
424    }
425  }
426
427  /**
428   * Validate that result contains two specified keys, exactly. It is assumed key A sorts before key
429   * B.
430   */
431  protected void assertDoubleResult(Result result, byte[] row, byte[] familyA, byte[] qualifierA,
432    byte[] valueA, byte[] familyB, byte[] qualifierB, byte[] valueB) {
433    assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
434      + Bytes.toString(result.getRow()) + "]", equals(row, result.getRow()));
435    assertEquals("Expected two keys but result contains " + result.size(), 2, result.size());
436    Cell[] kv = result.rawCells();
437    Cell kvA = kv[0];
438    assertTrue(
439      "(A) Expected family [" + Bytes.toString(familyA) + "] " + "Got family ["
440        + Bytes.toString(CellUtil.cloneFamily(kvA)) + "]",
441      equals(familyA, CellUtil.cloneFamily(kvA)));
442    assertTrue(
443      "(A) Expected qualifier [" + Bytes.toString(qualifierA) + "] " + "Got qualifier ["
444        + Bytes.toString(CellUtil.cloneQualifier(kvA)) + "]",
445      equals(qualifierA, CellUtil.cloneQualifier(kvA)));
446    assertTrue("(A) Expected value [" + Bytes.toString(valueA) + "] " + "Got value ["
447      + Bytes.toString(CellUtil.cloneValue(kvA)) + "]", equals(valueA, CellUtil.cloneValue(kvA)));
448    Cell kvB = kv[1];
449    assertTrue(
450      "(B) Expected family [" + Bytes.toString(familyB) + "] " + "Got family ["
451        + Bytes.toString(CellUtil.cloneFamily(kvB)) + "]",
452      equals(familyB, CellUtil.cloneFamily(kvB)));
453    assertTrue(
454      "(B) Expected qualifier [" + Bytes.toString(qualifierB) + "] " + "Got qualifier ["
455        + Bytes.toString(CellUtil.cloneQualifier(kvB)) + "]",
456      equals(qualifierB, CellUtil.cloneQualifier(kvB)));
457    assertTrue("(B) Expected value [" + Bytes.toString(valueB) + "] " + "Got value ["
458      + Bytes.toString(CellUtil.cloneValue(kvB)) + "]", equals(valueB, CellUtil.cloneValue(kvB)));
459  }
460
461  protected void assertSingleResult(Result result, byte[] row, byte[] family, byte[] qualifier,
462    byte[] value) {
463    assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
464      + Bytes.toString(result.getRow()) + "]", equals(row, result.getRow()));
465    assertEquals("Expected a single key but result contains " + result.size(), 1, result.size());
466    Cell kv = result.rawCells()[0];
467    assertTrue("Expected family [" + Bytes.toString(family) + "] " + "Got family ["
468      + Bytes.toString(CellUtil.cloneFamily(kv)) + "]", equals(family, CellUtil.cloneFamily(kv)));
469    assertTrue(
470      "Expected qualifier [" + Bytes.toString(qualifier) + "] " + "Got qualifier ["
471        + Bytes.toString(CellUtil.cloneQualifier(kv)) + "]",
472      equals(qualifier, CellUtil.cloneQualifier(kv)));
473    assertTrue("Expected value [" + Bytes.toString(value) + "] " + "Got value ["
474      + Bytes.toString(CellUtil.cloneValue(kv)) + "]", equals(value, CellUtil.cloneValue(kv)));
475  }
476
477  protected void assertSingleResult(Result result, byte[] row, byte[] family, byte[] qualifier,
478    long value) {
479    assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
480      + Bytes.toString(result.getRow()) + "]", equals(row, result.getRow()));
481    assertEquals("Expected a single key but result contains " + result.size(), 1, result.size());
482    Cell kv = result.rawCells()[0];
483    assertTrue("Expected family [" + Bytes.toString(family) + "] " + "Got family ["
484      + Bytes.toString(CellUtil.cloneFamily(kv)) + "]", equals(family, CellUtil.cloneFamily(kv)));
485    assertTrue(
486      "Expected qualifier [" + Bytes.toString(qualifier) + "] " + "Got qualifier ["
487        + Bytes.toString(CellUtil.cloneQualifier(kv)) + "]",
488      equals(qualifier, CellUtil.cloneQualifier(kv)));
489    assertEquals("Expected value [" + value + "] " + "Got value ["
490      + Bytes.toLong(CellUtil.cloneValue(kv)) + "]", value, Bytes.toLong(CellUtil.cloneValue(kv)));
491  }
492
493  protected void assertSingleResult(Result result, byte[] row, byte[] family, byte[] qualifier,
494    long ts, byte[] value) {
495    assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
496      + Bytes.toString(result.getRow()) + "]", equals(row, result.getRow()));
497    assertEquals("Expected a single key but result contains " + result.size(), 1, result.size());
498    Cell kv = result.rawCells()[0];
499    assertTrue("Expected family [" + Bytes.toString(family) + "] " + "Got family ["
500      + Bytes.toString(CellUtil.cloneFamily(kv)) + "]", equals(family, CellUtil.cloneFamily(kv)));
501    assertTrue(
502      "Expected qualifier [" + Bytes.toString(qualifier) + "] " + "Got qualifier ["
503        + Bytes.toString(CellUtil.cloneQualifier(kv)) + "]",
504      equals(qualifier, CellUtil.cloneQualifier(kv)));
505    assertEquals("Expected ts [" + ts + "] " + "Got ts [" + kv.getTimestamp() + "]", ts,
506      kv.getTimestamp());
507    assertTrue("Expected value [" + Bytes.toString(value) + "] " + "Got value ["
508      + Bytes.toString(CellUtil.cloneValue(kv)) + "]", equals(value, CellUtil.cloneValue(kv)));
509  }
510
511  protected void assertEmptyResult(Result result) throws Exception {
512    assertTrue("expected an empty result but result contains " + result.size() + " keys",
513      result.isEmpty());
514  }
515
516  protected void assertNullResult(Result result) throws Exception {
517    assertNull("expected null result but received a non-null result", result);
518  }
519
520  protected void getVersionRangeAndVerifyGreaterThan(Table ht, byte[] row, byte[] family,
521    byte[] qualifier, long[] stamps, byte[][] values, int start, int end) throws IOException {
522    Get get = new Get(row);
523    get.addColumn(family, qualifier);
524    get.readVersions(Integer.MAX_VALUE);
525    get.setTimeRange(stamps[start + 1], Long.MAX_VALUE);
526    Result result = ht.get(get);
527    assertNResult(result, row, family, qualifier, stamps, values, start + 1, end);
528  }
529
530  protected void getVersionRangeAndVerify(Table ht, byte[] row, byte[] family, byte[] qualifier,
531    long[] stamps, byte[][] values, int start, int end) throws IOException {
532    Get get = new Get(row);
533    get.addColumn(family, qualifier);
534    get.readVersions(Integer.MAX_VALUE);
535    get.setTimeRange(stamps[start], stamps[end] + 1);
536    Result result = ht.get(get);
537    assertNResult(result, row, family, qualifier, stamps, values, start, end);
538  }
539
540  protected void getAllVersionsAndVerify(Table ht, byte[] row, byte[] family, byte[] qualifier,
541    long[] stamps, byte[][] values, int start, int end) throws IOException {
542    Get get = new Get(row);
543    get.addColumn(family, qualifier);
544    get.readVersions(Integer.MAX_VALUE);
545    Result result = ht.get(get);
546    assertNResult(result, row, family, qualifier, stamps, values, start, end);
547  }
548
549  protected void scanVersionRangeAndVerifyGreaterThan(Table ht, byte[] row, byte[] family,
550    byte[] qualifier, long[] stamps, byte[][] values, int start, int end) throws IOException {
551    Scan scan = new Scan().withStartRow(row);
552    scan.addColumn(family, qualifier);
553    scan.readVersions(Integer.MAX_VALUE);
554    scan.setTimeRange(stamps[start + 1], Long.MAX_VALUE);
555    Result result = getSingleScanResult(ht, scan);
556    assertNResult(result, row, family, qualifier, stamps, values, start + 1, end);
557  }
558
559  protected void scanVersionRangeAndVerify(Table ht, byte[] row, byte[] family, byte[] qualifier,
560    long[] stamps, byte[][] values, int start, int end) throws IOException {
561    Scan scan = new Scan().withStartRow(row);
562    scan.addColumn(family, qualifier);
563    scan.readVersions(Integer.MAX_VALUE);
564    scan.setTimeRange(stamps[start], stamps[end] + 1);
565    Result result = getSingleScanResult(ht, scan);
566    assertNResult(result, row, family, qualifier, stamps, values, start, end);
567  }
568
569  protected void scanAllVersionsAndVerify(Table ht, byte[] row, byte[] family, byte[] qualifier,
570    long[] stamps, byte[][] values, int start, int end) throws IOException {
571    Scan scan = new Scan().withStartRow(row);
572    scan.addColumn(family, qualifier);
573    scan.readVersions(Integer.MAX_VALUE);
574    Result result = getSingleScanResult(ht, scan);
575    assertNResult(result, row, family, qualifier, stamps, values, start, end);
576  }
577
578  protected void getVersionAndVerify(Table ht, byte[] row, byte[] family, byte[] qualifier,
579    long stamp, byte[] value) throws Exception {
580    Get get = new Get(row);
581    get.addColumn(family, qualifier);
582    get.setTimestamp(stamp);
583    get.readVersions(Integer.MAX_VALUE);
584    Result result = ht.get(get);
585    assertSingleResult(result, row, family, qualifier, stamp, value);
586  }
587
588  protected void getVersionAndVerifyMissing(Table ht, byte[] row, byte[] family, byte[] qualifier,
589    long stamp) throws Exception {
590    Get get = new Get(row);
591    get.addColumn(family, qualifier);
592    get.setTimestamp(stamp);
593    get.readVersions(Integer.MAX_VALUE);
594    Result result = ht.get(get);
595    assertEmptyResult(result);
596  }
597
598  protected void scanVersionAndVerify(Table ht, byte[] row, byte[] family, byte[] qualifier,
599    long stamp, byte[] value) throws Exception {
600    Scan scan = new Scan().withStartRow(row);
601    scan.addColumn(family, qualifier);
602    scan.setTimestamp(stamp);
603    scan.readVersions(Integer.MAX_VALUE);
604    Result result = getSingleScanResult(ht, scan);
605    assertSingleResult(result, row, family, qualifier, stamp, value);
606  }
607
608  protected void scanVersionAndVerifyMissing(Table ht, byte[] row, byte[] family, byte[] qualifier,
609    long stamp) throws Exception {
610    Scan scan = new Scan().withStartRow(row);
611    scan.addColumn(family, qualifier);
612    scan.setTimestamp(stamp);
613    scan.readVersions(Integer.MAX_VALUE);
614    Result result = getSingleScanResult(ht, scan);
615    assertNullResult(result);
616  }
617
618  protected void getTestNull(Table ht, byte[] row, byte[] family, byte[] value) throws Exception {
619    Get get = new Get(row);
620    get.addColumn(family, null);
621    Result result = ht.get(get);
622    assertSingleResult(result, row, family, null, value);
623
624    get = new Get(row);
625    get.addColumn(family, HConstants.EMPTY_BYTE_ARRAY);
626    result = ht.get(get);
627    assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
628
629    get = new Get(row);
630    get.addFamily(family);
631    result = ht.get(get);
632    assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
633
634    get = new Get(row);
635    result = ht.get(get);
636    assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
637
638  }
639
640  protected void getTestNull(Table ht, byte[] row, byte[] family, long value) throws Exception {
641    Get get = new Get(row);
642    get.addColumn(family, null);
643    Result result = ht.get(get);
644    assertSingleResult(result, row, family, null, value);
645
646    get = new Get(row);
647    get.addColumn(family, HConstants.EMPTY_BYTE_ARRAY);
648    result = ht.get(get);
649    assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
650
651    get = new Get(row);
652    get.addFamily(family);
653    result = ht.get(get);
654    assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
655
656    get = new Get(row);
657    result = ht.get(get);
658    assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
659  }
660
661  protected void scanTestNull(Table ht, byte[] row, byte[] family, byte[] value) throws Exception {
662    scanTestNull(ht, row, family, value, false);
663  }
664
665  protected void scanTestNull(Table ht, byte[] row, byte[] family, byte[] value,
666    boolean isReversedScan) throws Exception {
667
668    Scan scan = new Scan();
669    scan.setReversed(isReversedScan);
670    scan.addColumn(family, null);
671    Result result = getSingleScanResult(ht, scan);
672    assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
673
674    scan = new Scan();
675    scan.setReversed(isReversedScan);
676    scan.addColumn(family, HConstants.EMPTY_BYTE_ARRAY);
677    result = getSingleScanResult(ht, scan);
678    assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
679
680    scan = new Scan();
681    scan.setReversed(isReversedScan);
682    scan.addFamily(family);
683    result = getSingleScanResult(ht, scan);
684    assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
685
686    scan = new Scan();
687    scan.setReversed(isReversedScan);
688    result = getSingleScanResult(ht, scan);
689    assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
690
691  }
692
693  protected void singleRowGetTest(Table ht, byte[][] ROWS, byte[][] FAMILIES, byte[][] QUALIFIERS,
694    byte[][] VALUES) throws Exception {
695    // Single column from memstore
696    Get get = new Get(ROWS[0]);
697    get.addColumn(FAMILIES[4], QUALIFIERS[0]);
698    Result result = ht.get(get);
699    assertSingleResult(result, ROWS[0], FAMILIES[4], QUALIFIERS[0], VALUES[0]);
700
701    // Single column from storefile
702    get = new Get(ROWS[0]);
703    get.addColumn(FAMILIES[2], QUALIFIERS[2]);
704    result = ht.get(get);
705    assertSingleResult(result, ROWS[0], FAMILIES[2], QUALIFIERS[2], VALUES[2]);
706
707    // Single column from storefile, family match
708    get = new Get(ROWS[0]);
709    get.addFamily(FAMILIES[7]);
710    result = ht.get(get);
711    assertSingleResult(result, ROWS[0], FAMILIES[7], QUALIFIERS[7], VALUES[7]);
712
713    // Two columns, one from memstore one from storefile, same family,
714    // wildcard match
715    get = new Get(ROWS[0]);
716    get.addFamily(FAMILIES[4]);
717    result = ht.get(get);
718    assertDoubleResult(result, ROWS[0], FAMILIES[4], QUALIFIERS[0], VALUES[0], FAMILIES[4],
719      QUALIFIERS[4], VALUES[4]);
720
721    // Two columns, one from memstore one from storefile, same family,
722    // explicit match
723    get = new Get(ROWS[0]);
724    get.addColumn(FAMILIES[4], QUALIFIERS[0]);
725    get.addColumn(FAMILIES[4], QUALIFIERS[4]);
726    result = ht.get(get);
727    assertDoubleResult(result, ROWS[0], FAMILIES[4], QUALIFIERS[0], VALUES[0], FAMILIES[4],
728      QUALIFIERS[4], VALUES[4]);
729
730    // Three column, one from memstore two from storefile, different families,
731    // wildcard match
732    get = new Get(ROWS[0]);
733    get.addFamily(FAMILIES[4]);
734    get.addFamily(FAMILIES[7]);
735    result = ht.get(get);
736    assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES,
737      new int[][] { { 4, 0, 0 }, { 4, 4, 4 }, { 7, 7, 7 } });
738
739    // Multiple columns from everywhere storefile, many family, wildcard
740    get = new Get(ROWS[0]);
741    get.addFamily(FAMILIES[2]);
742    get.addFamily(FAMILIES[4]);
743    get.addFamily(FAMILIES[6]);
744    get.addFamily(FAMILIES[7]);
745    result = ht.get(get);
746    assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES, new int[][] { { 2, 2, 2 },
747      { 2, 4, 4 }, { 4, 0, 0 }, { 4, 4, 4 }, { 6, 6, 6 }, { 6, 7, 7 }, { 7, 7, 7 } });
748
749    // Multiple columns from everywhere storefile, many family, wildcard
750    get = new Get(ROWS[0]);
751    get.addColumn(FAMILIES[2], QUALIFIERS[2]);
752    get.addColumn(FAMILIES[2], QUALIFIERS[4]);
753    get.addColumn(FAMILIES[4], QUALIFIERS[0]);
754    get.addColumn(FAMILIES[4], QUALIFIERS[4]);
755    get.addColumn(FAMILIES[6], QUALIFIERS[6]);
756    get.addColumn(FAMILIES[6], QUALIFIERS[7]);
757    get.addColumn(FAMILIES[7], QUALIFIERS[7]);
758    get.addColumn(FAMILIES[7], QUALIFIERS[8]);
759    result = ht.get(get);
760    assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES, new int[][] { { 2, 2, 2 },
761      { 2, 4, 4 }, { 4, 0, 0 }, { 4, 4, 4 }, { 6, 6, 6 }, { 6, 7, 7 }, { 7, 7, 7 } });
762
763    // Everything
764    get = new Get(ROWS[0]);
765    result = ht.get(get);
766    assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES, new int[][] { { 2, 2, 2 },
767      { 2, 4, 4 }, { 4, 0, 0 }, { 4, 4, 4 }, { 6, 6, 6 }, { 6, 7, 7 }, { 7, 7, 7 }, { 9, 0, 0 } });
768
769    // Get around inserted columns
770
771    get = new Get(ROWS[1]);
772    result = ht.get(get);
773    assertEmptyResult(result);
774
775    get = new Get(ROWS[0]);
776    get.addColumn(FAMILIES[4], QUALIFIERS[3]);
777    get.addColumn(FAMILIES[2], QUALIFIERS[3]);
778    result = ht.get(get);
779    assertEmptyResult(result);
780
781  }
782
783  protected void singleRowScanTest(Table ht, byte[][] ROWS, byte[][] FAMILIES, byte[][] QUALIFIERS,
784    byte[][] VALUES) throws Exception {
785    // Single column from memstore
786    Scan scan = new Scan();
787    scan.addColumn(FAMILIES[4], QUALIFIERS[0]);
788    Result result = getSingleScanResult(ht, scan);
789    assertSingleResult(result, ROWS[0], FAMILIES[4], QUALIFIERS[0], VALUES[0]);
790
791    // Single column from storefile
792    scan = new Scan();
793    scan.addColumn(FAMILIES[2], QUALIFIERS[2]);
794    result = getSingleScanResult(ht, scan);
795    assertSingleResult(result, ROWS[0], FAMILIES[2], QUALIFIERS[2], VALUES[2]);
796
797    // Single column from storefile, family match
798    scan = new Scan();
799    scan.addFamily(FAMILIES[7]);
800    result = getSingleScanResult(ht, scan);
801    assertSingleResult(result, ROWS[0], FAMILIES[7], QUALIFIERS[7], VALUES[7]);
802
803    // Two columns, one from memstore one from storefile, same family,
804    // wildcard match
805    scan = new Scan();
806    scan.addFamily(FAMILIES[4]);
807    result = getSingleScanResult(ht, scan);
808    assertDoubleResult(result, ROWS[0], FAMILIES[4], QUALIFIERS[0], VALUES[0], FAMILIES[4],
809      QUALIFIERS[4], VALUES[4]);
810
811    // Two columns, one from memstore one from storefile, same family,
812    // explicit match
813    scan = new Scan();
814    scan.addColumn(FAMILIES[4], QUALIFIERS[0]);
815    scan.addColumn(FAMILIES[4], QUALIFIERS[4]);
816    result = getSingleScanResult(ht, scan);
817    assertDoubleResult(result, ROWS[0], FAMILIES[4], QUALIFIERS[0], VALUES[0], FAMILIES[4],
818      QUALIFIERS[4], VALUES[4]);
819
820    // Three column, one from memstore two from storefile, different families,
821    // wildcard match
822    scan = new Scan();
823    scan.addFamily(FAMILIES[4]);
824    scan.addFamily(FAMILIES[7]);
825    result = getSingleScanResult(ht, scan);
826    assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES,
827      new int[][] { { 4, 0, 0 }, { 4, 4, 4 }, { 7, 7, 7 } });
828
829    // Multiple columns from everywhere storefile, many family, wildcard
830    scan = new Scan();
831    scan.addFamily(FAMILIES[2]);
832    scan.addFamily(FAMILIES[4]);
833    scan.addFamily(FAMILIES[6]);
834    scan.addFamily(FAMILIES[7]);
835    result = getSingleScanResult(ht, scan);
836    assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES, new int[][] { { 2, 2, 2 },
837      { 2, 4, 4 }, { 4, 0, 0 }, { 4, 4, 4 }, { 6, 6, 6 }, { 6, 7, 7 }, { 7, 7, 7 } });
838
839    // Multiple columns from everywhere storefile, many family, wildcard
840    scan = new Scan();
841    scan.addColumn(FAMILIES[2], QUALIFIERS[2]);
842    scan.addColumn(FAMILIES[2], QUALIFIERS[4]);
843    scan.addColumn(FAMILIES[4], QUALIFIERS[0]);
844    scan.addColumn(FAMILIES[4], QUALIFIERS[4]);
845    scan.addColumn(FAMILIES[6], QUALIFIERS[6]);
846    scan.addColumn(FAMILIES[6], QUALIFIERS[7]);
847    scan.addColumn(FAMILIES[7], QUALIFIERS[7]);
848    scan.addColumn(FAMILIES[7], QUALIFIERS[8]);
849    result = getSingleScanResult(ht, scan);
850    assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES, new int[][] { { 2, 2, 2 },
851      { 2, 4, 4 }, { 4, 0, 0 }, { 4, 4, 4 }, { 6, 6, 6 }, { 6, 7, 7 }, { 7, 7, 7 } });
852
853    // Everything
854    scan = new Scan();
855    result = getSingleScanResult(ht, scan);
856    assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES, new int[][] { { 2, 2, 2 },
857      { 2, 4, 4 }, { 4, 0, 0 }, { 4, 4, 4 }, { 6, 6, 6 }, { 6, 7, 7 }, { 7, 7, 7 }, { 9, 0, 0 } });
858
859    // Scan around inserted columns
860
861    scan = new Scan().withStartRow(ROWS[1]);
862    result = getSingleScanResult(ht, scan);
863    assertNullResult(result);
864
865    scan = new Scan();
866    scan.addColumn(FAMILIES[4], QUALIFIERS[3]);
867    scan.addColumn(FAMILIES[2], QUALIFIERS[3]);
868    result = getSingleScanResult(ht, scan);
869    assertNullResult(result);
870  }
871
872  /**
873   * Verify a single column using gets. Expects family and qualifier arrays to be valid for at least
874   * the range: idx-2 < idx < idx+2
875   */
876  protected void getVerifySingleColumn(Table ht, byte[][] ROWS, int ROWIDX, byte[][] FAMILIES,
877    int FAMILYIDX, byte[][] QUALIFIERS, int QUALIFIERIDX, byte[][] VALUES, int VALUEIDX)
878    throws Exception {
879    Get get = new Get(ROWS[ROWIDX]);
880    Result result = ht.get(get);
881    assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX],
882      VALUES[VALUEIDX]);
883
884    get = new Get(ROWS[ROWIDX]);
885    get.addFamily(FAMILIES[FAMILYIDX]);
886    result = ht.get(get);
887    assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX],
888      VALUES[VALUEIDX]);
889
890    get = new Get(ROWS[ROWIDX]);
891    get.addFamily(FAMILIES[FAMILYIDX - 2]);
892    get.addFamily(FAMILIES[FAMILYIDX]);
893    get.addFamily(FAMILIES[FAMILYIDX + 2]);
894    result = ht.get(get);
895    assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX],
896      VALUES[VALUEIDX]);
897
898    get = new Get(ROWS[ROWIDX]);
899    get.addColumn(FAMILIES[FAMILYIDX], QUALIFIERS[0]);
900    result = ht.get(get);
901    assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX],
902      VALUES[VALUEIDX]);
903
904    get = new Get(ROWS[ROWIDX]);
905    get.addColumn(FAMILIES[FAMILYIDX], QUALIFIERS[1]);
906    get.addFamily(FAMILIES[FAMILYIDX]);
907    result = ht.get(get);
908    assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX],
909      VALUES[VALUEIDX]);
910
911    get = new Get(ROWS[ROWIDX]);
912    get.addFamily(FAMILIES[FAMILYIDX]);
913    get.addColumn(FAMILIES[FAMILYIDX + 1], QUALIFIERS[1]);
914    get.addColumn(FAMILIES[FAMILYIDX - 2], QUALIFIERS[1]);
915    get.addFamily(FAMILIES[FAMILYIDX - 1]);
916    get.addFamily(FAMILIES[FAMILYIDX + 2]);
917    result = ht.get(get);
918    assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX],
919      VALUES[VALUEIDX]);
920
921  }
922
923  /**
924   * Verify a single column using scanners. Expects family and qualifier arrays to be valid for at
925   * least the range: idx-2 to idx+2 Expects row array to be valid for at least idx to idx+2
926   */
927  protected void scanVerifySingleColumn(Table ht, byte[][] ROWS, int ROWIDX, byte[][] FAMILIES,
928    int FAMILYIDX, byte[][] QUALIFIERS, int QUALIFIERIDX, byte[][] VALUES, int VALUEIDX)
929    throws Exception {
930    Scan scan = new Scan();
931    Result result = getSingleScanResult(ht, scan);
932    assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX],
933      VALUES[VALUEIDX]);
934
935    scan = new Scan().withStartRow(ROWS[ROWIDX]);
936    result = getSingleScanResult(ht, scan);
937    assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX],
938      VALUES[VALUEIDX]);
939
940    scan = new Scan().withStartRow(ROWS[ROWIDX]).withStopRow(ROWS[ROWIDX + 1], true);
941    result = getSingleScanResult(ht, scan);
942    assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX],
943      VALUES[VALUEIDX]);
944
945    scan = new Scan().withStartRow(HConstants.EMPTY_START_ROW).withStopRow(ROWS[ROWIDX + 1], true);
946    result = getSingleScanResult(ht, scan);
947    assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX],
948      VALUES[VALUEIDX]);
949
950    scan = new Scan();
951    scan.addFamily(FAMILIES[FAMILYIDX]);
952    result = getSingleScanResult(ht, scan);
953    assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX],
954      VALUES[VALUEIDX]);
955
956    scan = new Scan();
957    scan.addColumn(FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX]);
958    result = getSingleScanResult(ht, scan);
959    assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX],
960      VALUES[VALUEIDX]);
961
962    scan = new Scan();
963    scan.addColumn(FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX + 1]);
964    scan.addFamily(FAMILIES[FAMILYIDX]);
965    result = getSingleScanResult(ht, scan);
966    assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX],
967      VALUES[VALUEIDX]);
968
969    scan = new Scan();
970    scan.addColumn(FAMILIES[FAMILYIDX - 1], QUALIFIERS[QUALIFIERIDX + 1]);
971    scan.addColumn(FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX]);
972    scan.addFamily(FAMILIES[FAMILYIDX + 1]);
973    result = getSingleScanResult(ht, scan);
974    assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX],
975      VALUES[VALUEIDX]);
976
977  }
978
979  /**
980   * Verify we do not read any values by accident around a single column Same requirements as
981   * getVerifySingleColumn
982   */
983  protected void getVerifySingleEmpty(Table ht, byte[][] ROWS, int ROWIDX, byte[][] FAMILIES,
984    int FAMILYIDX, byte[][] QUALIFIERS, int QUALIFIERIDX) throws Exception {
985    Get get = new Get(ROWS[ROWIDX]);
986    get.addFamily(FAMILIES[4]);
987    get.addColumn(FAMILIES[4], QUALIFIERS[1]);
988    Result result = ht.get(get);
989    assertEmptyResult(result);
990
991    get = new Get(ROWS[ROWIDX]);
992    get.addFamily(FAMILIES[4]);
993    get.addColumn(FAMILIES[4], QUALIFIERS[2]);
994    result = ht.get(get);
995    assertEmptyResult(result);
996
997    get = new Get(ROWS[ROWIDX]);
998    get.addFamily(FAMILIES[3]);
999    get.addColumn(FAMILIES[4], QUALIFIERS[2]);
1000    get.addFamily(FAMILIES[5]);
1001    result = ht.get(get);
1002    assertEmptyResult(result);
1003
1004    get = new Get(ROWS[ROWIDX + 1]);
1005    result = ht.get(get);
1006    assertEmptyResult(result);
1007
1008  }
1009
1010  protected void scanVerifySingleEmpty(Table ht, byte[][] ROWS, int ROWIDX, byte[][] FAMILIES,
1011    int FAMILYIDX, byte[][] QUALIFIERS, int QUALIFIERIDX) throws Exception {
1012    Scan scan = new Scan().withStartRow(ROWS[ROWIDX + 1]);
1013    Result result = getSingleScanResult(ht, scan);
1014    assertNullResult(result);
1015
1016    scan = new Scan().withStartRow(ROWS[ROWIDX + 1]).withStopRow(ROWS[ROWIDX + 2], true);
1017    result = getSingleScanResult(ht, scan);
1018    assertNullResult(result);
1019
1020    scan = new Scan().withStartRow(HConstants.EMPTY_START_ROW).withStopRow(ROWS[ROWIDX]);
1021    result = getSingleScanResult(ht, scan);
1022    assertNullResult(result);
1023
1024    scan = new Scan();
1025    scan.addColumn(FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX + 1]);
1026    scan.addFamily(FAMILIES[FAMILYIDX - 1]);
1027    result = getSingleScanResult(ht, scan);
1028    assertNullResult(result);
1029
1030  }
1031}