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.types;
019
020import static org.junit.Assert.assertArrayEquals;
021import static org.junit.Assert.assertEquals;
022
023import org.apache.hadoop.hbase.HBaseClassTestRule;
024import org.apache.hadoop.hbase.testclassification.MiscTests;
025import org.apache.hadoop.hbase.testclassification.SmallTests;
026import org.apache.hadoop.hbase.util.Bytes;
027import org.apache.hadoop.hbase.util.Order;
028import org.apache.hadoop.hbase.util.PositionedByteRange;
029import org.apache.hadoop.hbase.util.SimplePositionedMutableByteRange;
030import org.junit.ClassRule;
031import org.junit.Test;
032import org.junit.experimental.categories.Category;
033
034@Category({ MiscTests.class, SmallTests.class })
035public class TestTerminatedWrapper {
036
037  @ClassRule
038  public static final HBaseClassTestRule CLASS_RULE =
039    HBaseClassTestRule.forClass(TestTerminatedWrapper.class);
040
041  static final String[] VALUES_STRINGS = new String[] { "", "1", "22", "333", "4444", "55555",
042    "666666", "7777777", "88888888", "999999999", };
043
044  static final byte[][] VALUES_BYTES = new byte[VALUES_STRINGS.length][];
045  static {
046    for (int i = 0; i < VALUES_STRINGS.length; i++) {
047      VALUES_BYTES[i] = Bytes.toBytes(VALUES_STRINGS[i]);
048    }
049  }
050
051  static final byte[][] TERMINATORS = new byte[][] { new byte[] { -2 }, Bytes.toBytes("foo") };
052
053  @Test(expected = IllegalArgumentException.class)
054  public void testEmptyDelimiter() {
055    new TerminatedWrapper<>(new RawBytes(Order.ASCENDING), "");
056  }
057
058  @Test(expected = IllegalArgumentException.class)
059  public void testNullDelimiter() {
060    new RawBytesTerminated((byte[]) null);
061    // new TerminatedWrapper<byte[]>(new RawBytes(), (byte[]) null);
062  }
063
064  @Test(expected = IllegalArgumentException.class)
065  public void testEncodedValueContainsTerm() {
066    final DataType<byte[]> type = new TerminatedWrapper<>(new RawBytes(Order.ASCENDING), "foo");
067    final PositionedByteRange buff = new SimplePositionedMutableByteRange(16);
068    type.encode(buff, Bytes.toBytes("hello foobar!"));
069  }
070
071  @Test
072  public void testReadWriteSkippable() {
073    final PositionedByteRange buff = new SimplePositionedMutableByteRange(14);
074    for (final OrderedString t : new OrderedString[] { new OrderedString(Order.ASCENDING),
075      new OrderedString(Order.DESCENDING) }) {
076      for (final byte[] term : TERMINATORS) {
077        for (final String val : VALUES_STRINGS) {
078          buff.setPosition(0);
079          final DataType<String> type = new TerminatedWrapper<>(t, term);
080          assertEquals(val.length() + 2 + term.length, type.encode(buff, val));
081          buff.setPosition(0);
082          assertEquals(val, type.decode(buff));
083          assertEquals(val.length() + 2 + term.length, buff.getPosition());
084        }
085      }
086    }
087  }
088
089  @Test
090  public void testReadWriteNonSkippable() {
091    PositionedByteRange buff = new SimplePositionedMutableByteRange(12);
092    for (Order ord : new Order[] { Order.ASCENDING, Order.DESCENDING }) {
093      for (byte[] term : TERMINATORS) {
094        for (byte[] val : VALUES_BYTES) {
095          buff.setPosition(0);
096          DataType<byte[]> type = new TerminatedWrapper<>(new RawBytes(ord), term);
097          assertEquals(val.length + term.length, type.encode(buff, val));
098          buff.setPosition(0);
099          assertArrayEquals(val, type.decode(buff));
100          assertEquals(val.length + term.length, buff.getPosition());
101        }
102      }
103    }
104  }
105
106  @Test
107  public void testSkipSkippable() {
108    final PositionedByteRange buff = new SimplePositionedMutableByteRange(14);
109    for (final OrderedString t : new OrderedString[] { new OrderedString(Order.ASCENDING),
110      new OrderedString(Order.DESCENDING) }) {
111      for (final byte[] term : TERMINATORS) {
112        for (final String val : VALUES_STRINGS) {
113          buff.setPosition(0);
114          final DataType<String> type = new TerminatedWrapper<>(t, term);
115          final int expected = val.length() + 2 + term.length;
116          assertEquals(expected, type.encode(buff, val));
117          buff.setPosition(0);
118          assertEquals(expected, type.skip(buff));
119          assertEquals(expected, buff.getPosition());
120        }
121      }
122    }
123  }
124
125  @Test
126  public void testSkipNonSkippable() {
127    PositionedByteRange buff = new SimplePositionedMutableByteRange(12);
128    for (Order ord : new Order[] { Order.ASCENDING, Order.DESCENDING }) {
129      for (byte[] term : TERMINATORS) {
130        for (byte[] val : VALUES_BYTES) {
131          buff.setPosition(0);
132          DataType<byte[]> type = new TerminatedWrapper<>(new RawBytes(ord), term);
133          int expected = type.encode(buff, val);
134          buff.setPosition(0);
135          assertEquals(expected, type.skip(buff));
136          assertEquals(expected, buff.getPosition());
137        }
138      }
139    }
140  }
141
142  @Test(expected = IllegalArgumentException.class)
143  public void testInvalidSkip() {
144    final PositionedByteRange buff = new SimplePositionedMutableByteRange(Bytes.toBytes("foo"));
145    final DataType<byte[]> type =
146      new TerminatedWrapper<>(new RawBytes(Order.ASCENDING), new byte[] { 0x00 });
147    type.skip(buff);
148  }
149}