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;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertFalse;
022import static org.junit.Assert.assertTrue;
023import static org.junit.Assert.fail;
024
025import java.io.ByteArrayOutputStream;
026import java.io.IOException;
027import java.math.BigDecimal;
028import java.nio.ByteBuffer;
029import java.util.ArrayList;
030import java.util.List;
031import java.util.NavigableMap;
032import java.util.TreeMap;
033import org.apache.hadoop.hbase.testclassification.MiscTests;
034import org.apache.hadoop.hbase.testclassification.SmallTests;
035import org.apache.hadoop.hbase.util.Bytes;
036import org.junit.Assert;
037import org.junit.ClassRule;
038import org.junit.Test;
039import org.junit.experimental.categories.Category;
040import org.mockito.Mockito;
041
042@Category({ MiscTests.class, SmallTests.class })
043public class TestCellUtil {
044  @ClassRule
045  public static final HBaseClassTestRule CLASS_RULE =
046    HBaseClassTestRule.forClass(TestCellUtil.class);
047
048  /**
049   * CellScannable used in test. Returns a {@link TestCellScanner}
050   */
051  private static class TestCellScannable implements CellScannable {
052    private final int cellsCount;
053
054    TestCellScannable(final int cellsCount) {
055      this.cellsCount = cellsCount;
056    }
057
058    @Override
059    public CellScanner cellScanner() {
060      return new TestCellScanner(this.cellsCount);
061    }
062  }
063
064  /**
065   * CellScanner used in test.
066   */
067  private static class TestCellScanner implements CellScanner {
068    private int count = 0;
069    private Cell current = null;
070    private final int cellsCount;
071
072    TestCellScanner(final int cellsCount) {
073      this.cellsCount = cellsCount;
074    }
075
076    @Override
077    public Cell current() {
078      return this.current;
079    }
080
081    @Override
082    public boolean advance() {
083      if (this.count < cellsCount) {
084        this.current = new TestCell(this.count);
085        this.count++;
086        return true;
087      }
088      return false;
089    }
090  }
091
092  /**
093   * Cell used in test. Has row only.
094   */
095  private static class TestCell implements Cell {
096    private final byte[] row;
097
098    TestCell(final int i) {
099      this.row = Bytes.toBytes(i);
100    }
101
102    @Override
103    public byte[] getRowArray() {
104      return this.row;
105    }
106
107    @Override
108    public int getRowOffset() {
109      return 0;
110    }
111
112    @Override
113    public short getRowLength() {
114      return (short) this.row.length;
115    }
116
117    @Override
118    public byte[] getFamilyArray() {
119      // TODO Auto-generated method stub
120      return null;
121    }
122
123    @Override
124    public int getFamilyOffset() {
125      // TODO Auto-generated method stub
126      return 0;
127    }
128
129    @Override
130    public byte getFamilyLength() {
131      // TODO Auto-generated method stub
132      return 0;
133    }
134
135    @Override
136    public byte[] getQualifierArray() {
137      // TODO Auto-generated method stub
138      return null;
139    }
140
141    @Override
142    public int getQualifierOffset() {
143      // TODO Auto-generated method stub
144      return 0;
145    }
146
147    @Override
148    public int getQualifierLength() {
149      // TODO Auto-generated method stub
150      return 0;
151    }
152
153    @Override
154    public long getTimestamp() {
155      // TODO Auto-generated method stub
156      return 0;
157    }
158
159    @Override
160    public byte getTypeByte() {
161      // TODO Auto-generated method stub
162      return 0;
163    }
164
165    @Override
166    public byte[] getValueArray() {
167      // TODO Auto-generated method stub
168      return null;
169    }
170
171    @Override
172    public int getValueOffset() {
173      // TODO Auto-generated method stub
174      return 0;
175    }
176
177    @Override
178    public int getValueLength() {
179      // TODO Auto-generated method stub
180      return 0;
181    }
182
183    @Override
184    public int getSerializedSize() {
185      return 0;
186    }
187
188    @Override
189    public byte[] getTagsArray() {
190      // TODO Auto-generated method stub
191      return null;
192    }
193
194    @Override
195    public int getTagsOffset() {
196      // TODO Auto-generated method stub
197      return 0;
198    }
199
200    @Override
201    public long getSequenceId() {
202      // TODO Auto-generated method stub
203      return 0;
204    }
205
206    @Override
207    public int getTagsLength() {
208      // TODO Auto-generated method stub
209      return 0;
210    }
211
212    @Override
213    public long heapSize() {
214      return 0;
215    }
216  }
217
218  /**
219   * Was overflowing if 100k or so lists of cellscanners to return.
220   */
221  @Test
222  public void testCreateCellScannerOverflow() throws IOException {
223    consume(doCreateCellScanner(1, 1), 1);
224    consume(doCreateCellScanner(3, 0), 0);
225    consume(doCreateCellScanner(3, 3), 3 * 3);
226    consume(doCreateCellScanner(0, 1), 0);
227    // Do big number. See HBASE-11813 for why.
228    final int hundredK = 100000;
229    consume(doCreateCellScanner(hundredK, 0), 0);
230    consume(doCreateCellArray(1), 1);
231    consume(doCreateCellArray(0), 0);
232    consume(doCreateCellArray(3), 3);
233    List<CellScannable> cells = new ArrayList<>(hundredK);
234    for (int i = 0; i < hundredK; i++) {
235      cells.add(new TestCellScannable(1));
236    }
237    consume(CellUtil.createCellScanner(cells), hundredK);
238    NavigableMap<byte[], List<Cell>> m = new TreeMap<>(Bytes.BYTES_COMPARATOR);
239    List<Cell> cellArray = new ArrayList<>(hundredK);
240    for (int i = 0; i < hundredK; i++) {
241      cellArray.add(new TestCell(i));
242    }
243    m.put(new byte[] { 'f' }, cellArray);
244    consume(CellUtil.createCellScanner(m), hundredK);
245  }
246
247  private CellScanner doCreateCellArray(final int itemsPerList) {
248    Cell[] cells = new Cell[itemsPerList];
249    for (int i = 0; i < itemsPerList; i++) {
250      cells[i] = new TestCell(i);
251    }
252    return CellUtil.createCellScanner(cells);
253  }
254
255  private CellScanner doCreateCellScanner(final int listsCount, final int itemsPerList) {
256    List<CellScannable> cells = new ArrayList<>(listsCount);
257    for (int i = 0; i < listsCount; i++) {
258      CellScannable cs = new CellScannable() {
259        @Override
260        public CellScanner cellScanner() {
261          return new TestCellScanner(itemsPerList);
262        }
263      };
264      cells.add(cs);
265    }
266    return CellUtil.createCellScanner(cells);
267  }
268
269  private void consume(final CellScanner scanner, final int expected) throws IOException {
270    int count = 0;
271    while (scanner.advance()) {
272      count++;
273    }
274    Assert.assertEquals(expected, count);
275  }
276
277  @Test
278  public void testOverlappingKeys() {
279    byte[] empty = HConstants.EMPTY_BYTE_ARRAY;
280    byte[] a = Bytes.toBytes("a");
281    byte[] b = Bytes.toBytes("b");
282    byte[] c = Bytes.toBytes("c");
283    byte[] d = Bytes.toBytes("d");
284
285    // overlaps
286    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, b, a, b));
287    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, c, a, b));
288    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, b, a, c));
289    Assert.assertTrue(PrivateCellUtil.overlappingKeys(b, c, a, c));
290    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, c, b, c));
291    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, d, b, c));
292    Assert.assertTrue(PrivateCellUtil.overlappingKeys(b, c, a, d));
293
294    Assert.assertTrue(PrivateCellUtil.overlappingKeys(empty, b, a, b));
295    Assert.assertTrue(PrivateCellUtil.overlappingKeys(empty, b, a, c));
296
297    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, b, empty, b));
298    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, b, empty, c));
299
300    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, empty, a, b));
301    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, empty, a, c));
302
303    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, b, empty, empty));
304    Assert.assertTrue(PrivateCellUtil.overlappingKeys(empty, empty, a, b));
305
306    // non overlaps
307    Assert.assertFalse(PrivateCellUtil.overlappingKeys(a, b, c, d));
308    Assert.assertFalse(PrivateCellUtil.overlappingKeys(c, d, a, b));
309
310    Assert.assertFalse(PrivateCellUtil.overlappingKeys(b, c, c, d));
311    Assert.assertFalse(PrivateCellUtil.overlappingKeys(b, c, c, empty));
312    Assert.assertFalse(PrivateCellUtil.overlappingKeys(b, c, d, empty));
313    Assert.assertFalse(PrivateCellUtil.overlappingKeys(c, d, b, c));
314    Assert.assertFalse(PrivateCellUtil.overlappingKeys(c, empty, b, c));
315    Assert.assertFalse(PrivateCellUtil.overlappingKeys(d, empty, b, c));
316
317    Assert.assertFalse(PrivateCellUtil.overlappingKeys(b, c, a, b));
318    Assert.assertFalse(PrivateCellUtil.overlappingKeys(b, c, empty, b));
319    Assert.assertFalse(PrivateCellUtil.overlappingKeys(b, c, empty, a));
320    Assert.assertFalse(PrivateCellUtil.overlappingKeys(a, b, b, c));
321    Assert.assertFalse(PrivateCellUtil.overlappingKeys(empty, b, b, c));
322    Assert.assertFalse(PrivateCellUtil.overlappingKeys(empty, a, b, c));
323  }
324
325  @Test
326  public void testFindCommonPrefixInFlatKey() {
327    // The whole key matching case
328    KeyValue kv1 =
329      new KeyValue(Bytes.toBytes("r1"), Bytes.toBytes("f1"), Bytes.toBytes("q1"), null);
330    Assert.assertEquals(kv1.getKeyLength(),
331      PrivateCellUtil.findCommonPrefixInFlatKey(kv1, kv1, true, true));
332    Assert.assertEquals(kv1.getKeyLength(),
333      PrivateCellUtil.findCommonPrefixInFlatKey(kv1, kv1, false, true));
334    Assert.assertEquals(kv1.getKeyLength() - KeyValue.TIMESTAMP_TYPE_SIZE,
335      PrivateCellUtil.findCommonPrefixInFlatKey(kv1, kv1, true, false));
336    // The rk length itself mismatch
337    KeyValue kv2 =
338      new KeyValue(Bytes.toBytes("r12"), Bytes.toBytes("f1"), Bytes.toBytes("q1"), null);
339    Assert.assertEquals(1, PrivateCellUtil.findCommonPrefixInFlatKey(kv1, kv2, true, true));
340    // part of rk is same
341    KeyValue kv3 =
342      new KeyValue(Bytes.toBytes("r14"), Bytes.toBytes("f1"), Bytes.toBytes("q1"), null);
343    Assert.assertEquals(KeyValue.ROW_LENGTH_SIZE + Bytes.toBytes("r1").length,
344      PrivateCellUtil.findCommonPrefixInFlatKey(kv2, kv3, true, true));
345    // entire rk is same but different cf name
346    KeyValue kv4 =
347      new KeyValue(Bytes.toBytes("r14"), Bytes.toBytes("f2"), Bytes.toBytes("q1"), null);
348    Assert.assertEquals(
349      KeyValue.ROW_LENGTH_SIZE + kv3.getRowLength() + KeyValue.FAMILY_LENGTH_SIZE
350        + Bytes.toBytes("f").length,
351      PrivateCellUtil.findCommonPrefixInFlatKey(kv3, kv4, false, true));
352    // rk and family are same and part of qualifier
353    KeyValue kv5 =
354      new KeyValue(Bytes.toBytes("r14"), Bytes.toBytes("f2"), Bytes.toBytes("q123"), null);
355    Assert.assertEquals(
356      KeyValue.ROW_LENGTH_SIZE + kv3.getRowLength() + KeyValue.FAMILY_LENGTH_SIZE
357        + kv4.getFamilyLength() + kv4.getQualifierLength(),
358      PrivateCellUtil.findCommonPrefixInFlatKey(kv4, kv5, true, true));
359    // rk, cf and q are same. ts differs
360    KeyValue kv6 = new KeyValue(Bytes.toBytes("rk"), 1234L);
361    KeyValue kv7 = new KeyValue(Bytes.toBytes("rk"), 1235L);
362    // only last byte out of 8 ts bytes in ts part differs
363    Assert.assertEquals(
364      KeyValue.ROW_LENGTH_SIZE + kv6.getRowLength() + KeyValue.FAMILY_LENGTH_SIZE
365        + kv6.getFamilyLength() + kv6.getQualifierLength() + 7,
366      PrivateCellUtil.findCommonPrefixInFlatKey(kv6, kv7, true, true));
367    // rk, cf, q and ts are same. Only type differs
368    KeyValue kv8 = new KeyValue(Bytes.toBytes("rk"), 1234L, KeyValue.Type.Delete);
369    Assert.assertEquals(
370      KeyValue.ROW_LENGTH_SIZE + kv6.getRowLength() + KeyValue.FAMILY_LENGTH_SIZE
371        + kv6.getFamilyLength() + kv6.getQualifierLength() + KeyValue.TIMESTAMP_SIZE,
372      PrivateCellUtil.findCommonPrefixInFlatKey(kv6, kv8, true, true));
373    // With out TS_TYPE check
374    Assert.assertEquals(
375      KeyValue.ROW_LENGTH_SIZE + kv6.getRowLength() + KeyValue.FAMILY_LENGTH_SIZE
376        + kv6.getFamilyLength() + kv6.getQualifierLength(),
377      PrivateCellUtil.findCommonPrefixInFlatKey(kv6, kv8, true, false));
378  }
379
380  /**
381   * Assert CellUtil makes Cell toStrings same way we do KeyValue toStrings.
382   */
383  @Test
384  public void testToString() {
385    byte[] row = Bytes.toBytes("row");
386    long ts = 123L;
387    // Make a KeyValue and a Cell and see if same toString result.
388    KeyValue kv = new KeyValue(row, HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY, ts,
389      KeyValue.Type.Minimum, HConstants.EMPTY_BYTE_ARRAY);
390    Cell cell = ExtendedCellBuilderFactory.create(CellBuilderType.DEEP_COPY).setRow(row)
391      .setFamily(HConstants.EMPTY_BYTE_ARRAY).setQualifier(HConstants.EMPTY_BYTE_ARRAY)
392      .setTimestamp(ts).setType(KeyValue.Type.Minimum.getCode())
393      .setValue(HConstants.EMPTY_BYTE_ARRAY).build();
394    String cellToString = CellUtil.getCellKeyAsString(cell);
395    assertEquals(kv.toString(), cellToString);
396    // Do another w/ non-null family.
397    byte[] f = new byte[] { 'f' };
398    byte[] q = new byte[] { 'q' };
399    kv = new KeyValue(row, f, q, ts, KeyValue.Type.Minimum, HConstants.EMPTY_BYTE_ARRAY);
400    cell = ExtendedCellBuilderFactory.create(CellBuilderType.DEEP_COPY).setRow(row).setFamily(f)
401      .setQualifier(q).setTimestamp(ts).setType(KeyValue.Type.Minimum.getCode())
402      .setValue(HConstants.EMPTY_BYTE_ARRAY).build();
403    cellToString = CellUtil.getCellKeyAsString(cell);
404    assertEquals(kv.toString(), cellToString);
405  }
406
407  @Test
408  public void testToString1() {
409    String row = "test.row";
410    String family = "test.family";
411    String qualifier = "test.qualifier";
412    long timestamp = 42;
413    KeyValue.Type type = KeyValue.Type.Put;
414    String value = "test.value";
415    long seqId = 1042;
416
417    Cell cell = ExtendedCellBuilderFactory.create(CellBuilderType.DEEP_COPY)
418      .setRow(Bytes.toBytes(row)).setFamily(Bytes.toBytes(family))
419      .setQualifier(Bytes.toBytes(qualifier)).setTimestamp(timestamp).setType(type.getCode())
420      .setValue(Bytes.toBytes(value)).setSequenceId(seqId).build();
421
422    String nonVerbose = CellUtil.toString(cell, false);
423    String verbose = CellUtil.toString(cell, true);
424
425    System.out.println("nonVerbose=" + nonVerbose);
426    System.out.println("verbose=" + verbose);
427
428    Assert.assertEquals(String.format("%s/%s:%s/%d/%s/vlen=%s/seqid=%s", row, family, qualifier,
429      timestamp, type.toString(), Bytes.toBytes(value).length, seqId), nonVerbose);
430
431    Assert.assertEquals(String.format("%s/%s:%s/%d/%s/vlen=%s/seqid=%s/%s", row, family, qualifier,
432      timestamp, type.toString(), Bytes.toBytes(value).length, seqId, value), verbose);
433
434    // TODO: test with tags
435  }
436
437  @Test
438  public void testCloneCellFieldsFromByteBufferedCell() {
439    byte[] r = Bytes.toBytes("row1");
440    byte[] f = Bytes.toBytes("cf1");
441    byte[] q = Bytes.toBytes("qual1");
442    byte[] v = Bytes.toBytes("val1");
443    byte[] tags = Bytes.toBytes("tag1");
444    KeyValue kv =
445      new KeyValue(r, f, q, 0, q.length, 1234L, KeyValue.Type.Put, v, 0, v.length, tags);
446    ByteBuffer buffer = ByteBuffer.wrap(kv.getBuffer());
447    Cell bbCell = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
448    byte[] rDest = CellUtil.cloneRow(bbCell);
449    assertTrue(Bytes.equals(r, rDest));
450    byte[] fDest = CellUtil.cloneFamily(bbCell);
451    assertTrue(Bytes.equals(f, fDest));
452    byte[] qDest = CellUtil.cloneQualifier(bbCell);
453    assertTrue(Bytes.equals(q, qDest));
454    byte[] vDest = CellUtil.cloneValue(bbCell);
455    assertTrue(Bytes.equals(v, vDest));
456    byte[] tDest = new byte[tags.length];
457    PrivateCellUtil.copyTagsTo(bbCell, tDest, 0);
458    assertTrue(Bytes.equals(tags, tDest));
459  }
460
461  @Test
462  public void testMatchingCellFieldsFromByteBufferedCell() {
463    byte[] r = Bytes.toBytes("row1");
464    byte[] f = Bytes.toBytes("cf1");
465    byte[] q1 = Bytes.toBytes("qual1");
466    byte[] q2 = Bytes.toBytes("qual2");
467    byte[] v = Bytes.toBytes("val1");
468    byte[] tags = Bytes.toBytes("tag1");
469    KeyValue kv =
470      new KeyValue(r, f, q1, 0, q1.length, 1234L, KeyValue.Type.Put, v, 0, v.length, tags);
471    ByteBuffer buffer = ByteBuffer.wrap(kv.getBuffer());
472    Cell bbCell1 = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
473    kv = new KeyValue(r, f, q2, 0, q2.length, 1234L, KeyValue.Type.Put, v, 0, v.length, tags);
474    buffer = ByteBuffer.wrap(kv.getBuffer());
475    Cell bbCell2 = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
476    assertTrue(CellUtil.matchingRows(bbCell1, bbCell2));
477    assertTrue(CellUtil.matchingRows(kv, bbCell2));
478    assertTrue(CellUtil.matchingRows(bbCell1, r));
479    assertTrue(CellUtil.matchingFamily(bbCell1, bbCell2));
480    assertTrue(CellUtil.matchingFamily(kv, bbCell2));
481    assertTrue(CellUtil.matchingFamily(bbCell1, f));
482    assertFalse(CellUtil.matchingQualifier(bbCell1, bbCell2));
483    assertTrue(CellUtil.matchingQualifier(kv, bbCell2));
484    assertTrue(CellUtil.matchingQualifier(bbCell1, q1));
485    assertTrue(CellUtil.matchingQualifier(bbCell2, q2));
486    assertTrue(CellUtil.matchingValue(bbCell1, bbCell2));
487    assertTrue(CellUtil.matchingValue(kv, bbCell2));
488    assertTrue(CellUtil.matchingValue(bbCell1, v));
489    assertFalse(CellUtil.matchingColumn(bbCell1, bbCell2));
490    assertTrue(CellUtil.matchingColumn(kv, bbCell2));
491    assertTrue(CellUtil.matchingColumn(bbCell1, f, q1));
492    assertTrue(CellUtil.matchingColumn(bbCell2, f, q2));
493  }
494
495  @Test
496  public void testCellFieldsAsPrimitiveTypesFromByteBufferedCell() {
497    int ri = 123;
498    byte[] r = Bytes.toBytes(ri);
499    byte[] f = Bytes.toBytes("cf1");
500    byte[] q = Bytes.toBytes("qual1");
501    long vl = 10981L;
502    byte[] v = Bytes.toBytes(vl);
503    KeyValue kv = new KeyValue(r, f, q, v);
504    ByteBuffer buffer = ByteBuffer.wrap(kv.getBuffer());
505    Cell bbCell = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
506    assertEquals(ri, PrivateCellUtil.getRowAsInt(bbCell));
507    assertEquals(vl, PrivateCellUtil.getValueAsLong(bbCell));
508    double vd = 3005.5;
509    v = Bytes.toBytes(vd);
510    kv = new KeyValue(r, f, q, v);
511    buffer = ByteBuffer.wrap(kv.getBuffer());
512    bbCell = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
513    assertEquals(vd, PrivateCellUtil.getValueAsDouble(bbCell), 0.0);
514    BigDecimal bd = new BigDecimal(9999);
515    v = Bytes.toBytes(bd);
516    kv = new KeyValue(r, f, q, v);
517    buffer = ByteBuffer.wrap(kv.getBuffer());
518    bbCell = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
519    assertEquals(bd, PrivateCellUtil.getValueAsBigDecimal(bbCell));
520  }
521
522  @Test
523  public void testWriteCell() throws IOException {
524    byte[] r = Bytes.toBytes("row1");
525    byte[] f = Bytes.toBytes("cf1");
526    byte[] q1 = Bytes.toBytes("qual1");
527    byte[] v = Bytes.toBytes("val1");
528    byte[] tags = Bytes.toBytes("tag1");
529    KeyValue kv =
530      new KeyValue(r, f, q1, 0, q1.length, 1234L, KeyValue.Type.Put, v, 0, v.length, tags);
531    NonExtendedCell nonExtCell = new NonExtendedCell(kv);
532    ByteArrayOutputStream os = new ByteArrayOutputStream();
533    PrivateCellUtil.writeCell(nonExtCell, os, true);
534    byte[] byteArray = os.toByteArray();
535    KeyValue res = new KeyValue(byteArray);
536    assertTrue(CellUtil.equals(kv, res));
537  }
538
539  // Workaround for jdk 11 - reflective access to interface default methods for testGetType
540  private static abstract class CellForMockito implements Cell {
541  }
542
543  @Test
544  public void testGetType() {
545    CellForMockito c = Mockito.mock(CellForMockito.class);
546    Mockito.when(c.getType()).thenCallRealMethod();
547    for (Cell.Type type : Cell.Type.values()) {
548      Mockito.when(c.getTypeByte()).thenReturn(type.getCode());
549      assertEquals(type, c.getType());
550    }
551
552    try {
553      Mockito.when(c.getTypeByte()).thenReturn(KeyValue.Type.Maximum.getCode());
554      c.getType();
555      fail("The code of Maximum can't be handled by Cell.Type");
556    } catch (UnsupportedOperationException e) {
557    }
558
559    try {
560      Mockito.when(c.getTypeByte()).thenReturn(KeyValue.Type.Minimum.getCode());
561      c.getType();
562      fail("The code of Maximum can't be handled by Cell.Type");
563    } catch (UnsupportedOperationException e) {
564    }
565  }
566
567  private static class NonExtendedCell implements Cell {
568    private KeyValue kv;
569
570    public NonExtendedCell(KeyValue kv) {
571      this.kv = kv;
572    }
573
574    @Override
575    public byte[] getRowArray() {
576      return this.kv.getRowArray();
577    }
578
579    @Override
580    public int getRowOffset() {
581      return this.kv.getRowOffset();
582    }
583
584    @Override
585    public short getRowLength() {
586      return this.kv.getRowLength();
587    }
588
589    @Override
590    public byte[] getFamilyArray() {
591      return this.kv.getFamilyArray();
592    }
593
594    @Override
595    public int getFamilyOffset() {
596      return this.kv.getFamilyOffset();
597    }
598
599    @Override
600    public byte getFamilyLength() {
601      return this.kv.getFamilyLength();
602    }
603
604    @Override
605    public byte[] getQualifierArray() {
606      return this.kv.getQualifierArray();
607    }
608
609    @Override
610    public int getQualifierOffset() {
611      return this.kv.getQualifierOffset();
612    }
613
614    @Override
615    public int getQualifierLength() {
616      return this.kv.getQualifierLength();
617    }
618
619    @Override
620    public long getTimestamp() {
621      return this.kv.getTimestamp();
622    }
623
624    @Override
625    public byte getTypeByte() {
626      return this.kv.getTypeByte();
627    }
628
629    @Override
630    public long getSequenceId() {
631      return this.kv.getSequenceId();
632    }
633
634    @Override
635    public byte[] getValueArray() {
636      return this.kv.getValueArray();
637    }
638
639    @Override
640    public int getValueOffset() {
641      return this.kv.getValueOffset();
642    }
643
644    @Override
645    public int getValueLength() {
646      return this.kv.getValueLength();
647    }
648
649    @Override
650    public int getSerializedSize() {
651      return this.kv.getSerializedSize();
652    }
653
654    @Override
655    public byte[] getTagsArray() {
656      return this.kv.getTagsArray();
657    }
658
659    @Override
660    public int getTagsOffset() {
661      return this.kv.getTagsOffset();
662    }
663
664    @Override
665    public int getTagsLength() {
666      return this.kv.getTagsLength();
667    }
668
669    @Override
670    public long heapSize() {
671      return this.kv.heapSize();
672    }
673  }
674}