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