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