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