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.io.hfile; 019 020import static org.junit.Assert.*; 021import static org.mockito.Mockito.*; 022 023import java.io.IOException; 024import org.apache.hadoop.fs.FSDataInputStream; 025import org.apache.hadoop.hbase.HBaseClassTestRule; 026import org.apache.hadoop.hbase.testclassification.IOTests; 027import org.apache.hadoop.hbase.testclassification.SmallTests; 028import org.junit.ClassRule; 029import org.junit.Rule; 030import org.junit.Test; 031import org.junit.experimental.categories.Category; 032import org.junit.rules.ExpectedException; 033 034/** 035 * Unit test suite covering HFileBlock positional read logic. 036 */ 037@Category({IOTests.class, SmallTests.class}) 038public class TestHFileBlockPositionalRead { 039 040 @ClassRule 041 public static final HBaseClassTestRule CLASS_RULE = 042 HBaseClassTestRule.forClass(TestHFileBlockPositionalRead.class); 043 044 @Rule 045 public ExpectedException exception = ExpectedException.none(); 046 047 @Test 048 public void testPositionalReadNoExtra() throws IOException { 049 long position = 0; 050 int bufOffset = 0; 051 int necessaryLen = 10; 052 int extraLen = 0; 053 int totalLen = necessaryLen + extraLen; 054 byte[] buf = new byte[totalLen]; 055 FSDataInputStream in = mock(FSDataInputStream.class); 056 when(in.read(position, buf, bufOffset, totalLen)).thenReturn(totalLen); 057 boolean ret = HFileBlock.positionalReadWithExtra(in, position, buf, 058 bufOffset, necessaryLen, extraLen); 059 assertFalse("Expect false return when no extra bytes requested", ret); 060 verify(in).read(position, buf, bufOffset, totalLen); 061 verifyNoMoreInteractions(in); 062 } 063 064 @Test 065 public void testPositionalReadShortReadOfNecessaryBytes() throws IOException { 066 long position = 0; 067 int bufOffset = 0; 068 int necessaryLen = 10; 069 int extraLen = 0; 070 int totalLen = necessaryLen + extraLen; 071 byte[] buf = new byte[totalLen]; 072 FSDataInputStream in = mock(FSDataInputStream.class); 073 when(in.read(position, buf, bufOffset, totalLen)).thenReturn(5); 074 when(in.read(5, buf, 5, 5)).thenReturn(5); 075 boolean ret = HFileBlock.positionalReadWithExtra(in, position, buf, 076 bufOffset, necessaryLen, extraLen); 077 assertFalse("Expect false return when no extra bytes requested", ret); 078 verify(in).read(position, buf, bufOffset, totalLen); 079 verify(in).read(5, buf, 5, 5); 080 verifyNoMoreInteractions(in); 081 } 082 083 @Test 084 public void testPositionalReadExtraSucceeded() throws IOException { 085 long position = 0; 086 int bufOffset = 0; 087 int necessaryLen = 10; 088 int extraLen = 5; 089 int totalLen = necessaryLen + extraLen; 090 byte[] buf = new byte[totalLen]; 091 FSDataInputStream in = mock(FSDataInputStream.class); 092 when(in.read(position, buf, bufOffset, totalLen)).thenReturn(totalLen); 093 boolean ret = HFileBlock.positionalReadWithExtra(in, position, buf, 094 bufOffset, necessaryLen, extraLen); 095 assertTrue("Expect true return when reading extra bytes succeeds", ret); 096 verify(in).read(position, buf, bufOffset, totalLen); 097 verifyNoMoreInteractions(in); 098 } 099 100 @Test 101 public void testPositionalReadExtraFailed() throws IOException { 102 long position = 0; 103 int bufOffset = 0; 104 int necessaryLen = 10; 105 int extraLen = 5; 106 int totalLen = necessaryLen + extraLen; 107 byte[] buf = new byte[totalLen]; 108 FSDataInputStream in = mock(FSDataInputStream.class); 109 when(in.read(position, buf, bufOffset, totalLen)).thenReturn(necessaryLen); 110 boolean ret = HFileBlock.positionalReadWithExtra(in, position, buf, 111 bufOffset, necessaryLen, extraLen); 112 assertFalse("Expect false return when reading extra bytes fails", ret); 113 verify(in).read(position, buf, bufOffset, totalLen); 114 verifyNoMoreInteractions(in); 115 } 116 117 @Test 118 public void testPositionalReadShortReadCompletesNecessaryAndExtraBytes() 119 throws IOException { 120 long position = 0; 121 int bufOffset = 0; 122 int necessaryLen = 10; 123 int extraLen = 5; 124 int totalLen = necessaryLen + extraLen; 125 byte[] buf = new byte[totalLen]; 126 FSDataInputStream in = mock(FSDataInputStream.class); 127 when(in.read(position, buf, bufOffset, totalLen)).thenReturn(5); 128 when(in.read(5, buf, 5, 10)).thenReturn(10); 129 boolean ret = HFileBlock.positionalReadWithExtra(in, position, buf, 130 bufOffset, necessaryLen, extraLen); 131 assertTrue("Expect true return when reading extra bytes succeeds", ret); 132 verify(in).read(position, buf, bufOffset, totalLen); 133 verify(in).read(5, buf, 5, 10); 134 verifyNoMoreInteractions(in); 135 } 136 137 @Test 138 public void testPositionalReadPrematureEOF() throws IOException { 139 long position = 0; 140 int bufOffset = 0; 141 int necessaryLen = 10; 142 int extraLen = 0; 143 int totalLen = necessaryLen + extraLen; 144 byte[] buf = new byte[totalLen]; 145 FSDataInputStream in = mock(FSDataInputStream.class); 146 when(in.read(position, buf, bufOffset, totalLen)).thenReturn(9); 147 when(in.read(position, buf, bufOffset, totalLen)).thenReturn(-1); 148 exception.expect(IOException.class); 149 exception.expectMessage("EOF"); 150 HFileBlock.positionalReadWithExtra(in, position, buf, bufOffset, 151 necessaryLen, extraLen); 152 } 153}