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[] q2 = Bytes.toBytes("qual2");
528    byte[] v = Bytes.toBytes("val1");
529    byte[] tags = Bytes.toBytes("tag1");
530    KeyValue kv =
531      new KeyValue(r, f, q1, 0, q1.length, 1234L, KeyValue.Type.Put, v, 0, v.length, tags);
532    NonExtendedCell nonExtCell = new NonExtendedCell(kv);
533    ByteArrayOutputStream os = new ByteArrayOutputStream();
534    int writeCell = PrivateCellUtil.writeCell(nonExtCell, os, true);
535    byte[] byteArray = os.toByteArray();
536    KeyValue res = new KeyValue(byteArray);
537    assertTrue(CellUtil.equals(kv, res));
538  }
539
540  // Workaround for jdk 11 - reflective access to interface default methods for testGetType
541  private abstract class CellForMockito implements Cell {
542  }
543
544  @Test
545  public void testGetType() {
546    CellForMockito c = Mockito.mock(CellForMockito.class);
547    Mockito.when(c.getType()).thenCallRealMethod();
548    for (CellForMockito.Type type : CellForMockito.Type.values()) {
549      Mockito.when(c.getTypeByte()).thenReturn(type.getCode());
550      assertEquals(type, c.getType());
551    }
552
553    try {
554      Mockito.when(c.getTypeByte()).thenReturn(KeyValue.Type.Maximum.getCode());
555      c.getType();
556      fail("The code of Maximum can't be handled by Cell.Type");
557    } catch (UnsupportedOperationException e) {
558    }
559
560    try {
561      Mockito.when(c.getTypeByte()).thenReturn(KeyValue.Type.Minimum.getCode());
562      c.getType();
563      fail("The code of Maximum can't be handled by Cell.Type");
564    } catch (UnsupportedOperationException e) {
565    }
566  }
567
568  private static class NonExtendedCell implements Cell {
569    private KeyValue kv;
570
571    public NonExtendedCell(KeyValue kv) {
572      this.kv = kv;
573    }
574
575    @Override
576    public byte[] getRowArray() {
577      return this.kv.getRowArray();
578    }
579
580    @Override
581    public int getRowOffset() {
582      return this.kv.getRowOffset();
583    }
584
585    @Override
586    public short getRowLength() {
587      return this.kv.getRowLength();
588    }
589
590    @Override
591    public byte[] getFamilyArray() {
592      return this.kv.getFamilyArray();
593    }
594
595    @Override
596    public int getFamilyOffset() {
597      return this.kv.getFamilyOffset();
598    }
599
600    @Override
601    public byte getFamilyLength() {
602      return this.kv.getFamilyLength();
603    }
604
605    @Override
606    public byte[] getQualifierArray() {
607      return this.kv.getQualifierArray();
608    }
609
610    @Override
611    public int getQualifierOffset() {
612      return this.kv.getQualifierOffset();
613    }
614
615    @Override
616    public int getQualifierLength() {
617      return this.kv.getQualifierLength();
618    }
619
620    @Override
621    public long getTimestamp() {
622      return this.kv.getTimestamp();
623    }
624
625    @Override
626    public byte getTypeByte() {
627      return this.kv.getTypeByte();
628    }
629
630    @Override
631    public long getSequenceId() {
632      return this.kv.getSequenceId();
633    }
634
635    @Override
636    public byte[] getValueArray() {
637      return this.kv.getValueArray();
638    }
639
640    @Override
641    public int getValueOffset() {
642      return this.kv.getValueOffset();
643    }
644
645    @Override
646    public int getValueLength() {
647      return this.kv.getValueLength();
648    }
649
650    @Override
651    public int getSerializedSize() {
652      return this.kv.getSerializedSize();
653    }
654
655    @Override
656    public byte[] getTagsArray() {
657      return this.kv.getTagsArray();
658    }
659
660    @Override
661    public int getTagsOffset() {
662      return this.kv.getTagsOffset();
663    }
664
665    @Override
666    public int getTagsLength() {
667      return this.kv.getTagsLength();
668    }
669
670    @Override
671    public long heapSize() {
672      return this.kv.heapSize();
673    }
674  }
675}