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