github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/clients/hadoopfs/src/test/java/io/lakefs/storage/HttpRangeInputStreamTest.java (about)

     1  package io.lakefs.storage;
     2  
     3  import java.io.EOFException;
     4  import java.io.IOException;
     5  import java.util.HashMap;
     6  import java.util.Map;
     7  
     8  import org.apache.commons.io.IOUtils;
     9  import org.apache.commons.lang3.RandomStringUtils;
    10  import org.apache.commons.lang3.StringUtils;
    11  import org.apache.hadoop.fs.FSExceptionMessages;
    12  import org.junit.After;
    13  import org.junit.Assert;
    14  import org.junit.Before;
    15  import org.junit.Test;
    16  
    17  import okhttp3.HttpUrl;
    18  import okhttp3.mockwebserver.Dispatcher;
    19  import okhttp3.mockwebserver.MockResponse;
    20  import okhttp3.mockwebserver.MockWebServer;
    21  import okhttp3.mockwebserver.RecordedRequest;
    22  
    23  public class HttpRangeInputStreamTest {
    24  
    25      final Dispatcher dispatcher = new Dispatcher() {
    26          Map<Integer, String> contentByLength = new HashMap<>();
    27  
    28          @Override
    29          public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
    30              int contentLength = Integer.valueOf(StringUtils.substringAfterLast(request.getPath(), "/"));
    31              String content = contentByLength.get(contentLength);
    32              if (content == null) {
    33                  content = RandomStringUtils.randomAlphanumeric(contentLength);
    34              }
    35              String[] range = StringUtils.substringAfter(request.getHeader("Range"), "bytes=").split("-");
    36              int start = Integer.valueOf(range[0]);
    37              int end = Integer.valueOf(range[1]);
    38              return new MockResponse()
    39                      .setHeader("Content-Range", String.format("bytes %d-%d/%d", start, end, contentLength))
    40                      .setResponseCode(200)
    41                      .setBody(content.substring(start, end));
    42          }
    43      };
    44      private MockWebServer server;
    45  
    46      @Before
    47      public void init() throws Exception {
    48          server = new MockWebServer();
    49          server.setDispatcher(dispatcher);
    50          server.start(1080);
    51      }
    52  
    53      @After
    54      public void tearDown() throws Exception {
    55          server.shutdown();
    56      }
    57  
    58      @Test
    59      public void testReadBigBuffer() throws IOException {
    60          HttpUrl url = server.url("/100");
    61          HttpRangeInputStream stream = new HttpRangeInputStream(url.toString(), 1000);
    62          byte[] buffer = new byte[25];
    63          IOUtils.readFully(stream, buffer);
    64          Assert.assertEquals(25, stream.getPos());
    65          Assert.assertEquals(75, stream.available());
    66          buffer = new byte[75];
    67  
    68          IOUtils.readFully(stream, buffer);
    69          Assert.assertEquals(100, stream.getPos());
    70          Assert.assertEquals(0, stream.available());
    71  
    72          stream.close();
    73      }
    74  
    75      @Test
    76      public void testReadSmallBuffer() throws IOException {
    77          HttpUrl url = server.url("/100");
    78          HttpRangeInputStream stream = new HttpRangeInputStream(url.toString(), 7);
    79          byte[] buffer = new byte[25];
    80          IOUtils.readFully(stream, buffer);
    81          Assert.assertEquals(25, stream.getPos());
    82          Assert.assertEquals(75, stream.available());
    83          buffer = new byte[75];
    84  
    85          IOUtils.readFully(stream, buffer);
    86          Assert.assertEquals(100, stream.getPos());
    87          Assert.assertEquals(0, stream.available());
    88          stream.close();
    89      }
    90  
    91      @Test
    92      public void testEmptyFile() throws IOException {
    93          HttpUrl url = server.url("/0");
    94          HttpRangeInputStream stream = new HttpRangeInputStream(url.toString(), 1000);
    95          Assert.assertEquals(0, stream.getPos());
    96          Assert.assertEquals(0, stream.available());
    97  
    98          byte[] buffer = new byte[0];
    99          IOUtils.readFully(stream, buffer);
   100          Assert.assertEquals(0, stream.getPos());
   101          Assert.assertEquals(0, stream.available());
   102          stream.close();
   103      }
   104  
   105      @Test
   106      public void testSeek() throws IOException {
   107          HttpUrl url = server.url("/100");
   108          HttpRangeInputStream stream = new HttpRangeInputStream(url.toString(), 7);
   109          byte[] buffer = new byte[3];
   110  
   111          stream.seek(20);
   112          Assert.assertEquals(20, stream.getPos());
   113          Assert.assertEquals(80, stream.available());
   114          IOUtils.readFully(stream, buffer);
   115          Assert.assertEquals(23, stream.getPos());
   116          Assert.assertEquals(77, stream.available());
   117  
   118          stream.seek(60);
   119          Assert.assertEquals(60, stream.getPos());
   120          Assert.assertEquals(40, stream.available());
   121          IOUtils.readFully(stream, buffer);
   122          Assert.assertEquals(63, stream.getPos());
   123          Assert.assertEquals(37, stream.available());
   124  
   125          stream.seek(97);
   126          Assert.assertEquals(97, stream.getPos());
   127          Assert.assertEquals(3, stream.available());
   128          IOUtils.readFully(stream, buffer);
   129          Assert.assertEquals(100, stream.getPos());
   130          Assert.assertEquals(0, stream.available());
   131  
   132          Assert.assertEquals(4, server.getRequestCount());
   133          stream.close();
   134      }
   135  
   136      @Test
   137      public void testSeekAfterEnd() throws IOException {
   138          HttpUrl url = server.url("/100");
   139          HttpRangeInputStream stream = new HttpRangeInputStream(url.toString(), 7);
   140          stream.seek(101);
   141          Assert.assertEquals(-1, stream.read());
   142          stream.close();
   143      }
   144  
   145      @Test
   146      public void testSeekBeforeStart() throws IOException {
   147          HttpUrl url = server.url("/100");
   148          HttpRangeInputStream stream = new HttpRangeInputStream(url.toString(), 7);
   149          Exception exception = Assert.assertThrows(EOFException.class, () -> stream.seek(-1));
   150          Assert.assertTrue(String.format("Exception message should contain %s", FSExceptionMessages.NEGATIVE_SEEK),
   151                  exception.getMessage().contains(FSExceptionMessages.NEGATIVE_SEEK));
   152          stream.close();
   153      }
   154  }