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.ipc;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertFalse;
022import static org.junit.Assert.assertTrue;
023
024import java.io.File;
025import java.io.FileOutputStream;
026import java.io.IOException;
027import java.nio.ByteBuffer;
028import java.nio.channels.FileChannel;
029import org.apache.hadoop.hbase.HBaseClassTestRule;
030import org.apache.hadoop.hbase.testclassification.RPCTests;
031import org.apache.hadoop.hbase.testclassification.SmallTests;
032import org.apache.hadoop.hbase.util.Bytes;
033import org.junit.After;
034import org.junit.Before;
035import org.junit.ClassRule;
036import org.junit.Test;
037import org.junit.experimental.categories.Category;
038
039import org.apache.hbase.thirdparty.com.google.common.base.Charsets;
040import org.apache.hbase.thirdparty.com.google.common.io.Files;
041
042@Category({ RPCTests.class, SmallTests.class })
043public class TestBufferChain {
044
045  @ClassRule
046  public static final HBaseClassTestRule CLASS_RULE =
047    HBaseClassTestRule.forClass(TestBufferChain.class);
048
049  private File tmpFile;
050
051  private static final byte[][] HELLO_WORLD_CHUNKS =
052    new byte[][] { "hello".getBytes(Charsets.UTF_8), " ".getBytes(Charsets.UTF_8),
053      "world".getBytes(Charsets.UTF_8) };
054
055  @Before
056  public void setup() throws IOException {
057    tmpFile = File.createTempFile("TestBufferChain", "txt");
058  }
059
060  @After
061  public void teardown() {
062    tmpFile.delete();
063  }
064
065  @Test
066  public void testGetBackBytesWePutIn() {
067    ByteBuffer[] bufs = wrapArrays(HELLO_WORLD_CHUNKS);
068    BufferChain chain = new BufferChain(bufs);
069    assertTrue(Bytes.equals(Bytes.toBytes("hello world"), chain.getBytes()));
070  }
071
072  @Test
073  public void testLimitOffset() throws IOException {
074    ByteBuffer[] bufs = new ByteBuffer[] { stringBuf("XXXhelloYYY", 3, 5), stringBuf(" ", 0, 1),
075      stringBuf("XXXXworldY", 4, 5) };
076    BufferChain chain = new BufferChain(bufs);
077    writeAndVerify(chain, "hello world");
078    assertNoRemaining(bufs);
079  }
080
081  private ByteBuffer stringBuf(String string, int position, int length) {
082    ByteBuffer buf = ByteBuffer.wrap(string.getBytes(Charsets.UTF_8));
083    buf.position(position);
084    buf.limit(position + length);
085    assertTrue(buf.hasRemaining());
086    return buf;
087  }
088
089  private void assertNoRemaining(ByteBuffer[] bufs) {
090    for (ByteBuffer buf : bufs) {
091      assertFalse(buf.hasRemaining());
092    }
093  }
094
095  private ByteBuffer[] wrapArrays(byte[][] arrays) {
096    ByteBuffer[] ret = new ByteBuffer[arrays.length];
097    for (int i = 0; i < arrays.length; i++) {
098      ret[i] = ByteBuffer.wrap(arrays[i]);
099    }
100    return ret;
101  }
102
103  private void writeAndVerify(BufferChain chain, String string) throws IOException {
104    FileOutputStream fos = new FileOutputStream(tmpFile);
105    FileChannel ch = fos.getChannel();
106    try {
107      long remaining = string.length();
108      while (chain.hasRemaining()) {
109        long n = chain.write(ch);
110        remaining -= n;
111      }
112      assertEquals(0, remaining);
113    } finally {
114      fos.close();
115    }
116    assertFalse(chain.hasRemaining());
117    assertEquals(string, Files.toString(tmpFile, Charsets.UTF_8));
118  }
119}