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(), ""); 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 DataType<byte[]> type = new TerminatedWrapper<>(new RawBytes(), "foo"); 067 PositionedByteRange buff = new SimplePositionedMutableByteRange(16); 068 type.encode(buff, Bytes.toBytes("hello foobar!")); 069 } 070 071 @Test 072 public void testReadWriteSkippable() { 073 PositionedByteRange buff = new SimplePositionedMutableByteRange(14); 074 for (OrderedString t : new OrderedString[] { OrderedString.ASCENDING, 075 OrderedString.DESCENDING }) { 076 for (byte[] term : TERMINATORS) { 077 for (String val : VALUES_STRINGS) { 078 buff.setPosition(0); 079 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 PositionedByteRange buff = new SimplePositionedMutableByteRange(14); 109 for (OrderedString t : new OrderedString[] { OrderedString.ASCENDING, 110 OrderedString.DESCENDING }) { 111 for (byte[] term : TERMINATORS) { 112 for (String val : VALUES_STRINGS) { 113 buff.setPosition(0); 114 DataType<String> type = new TerminatedWrapper<>(t, term); 115 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 PositionedByteRange buff = new SimplePositionedMutableByteRange(Bytes.toBytes("foo")); 145 DataType<byte[]> type = new TerminatedWrapper<>(new RawBytes(), new byte[] { 0x00 }); 146 type.skip(buff); 147 } 148}