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