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;
019
020import static org.junit.jupiter.api.Assertions.assertEquals;
021import static org.junit.jupiter.api.Assertions.assertFalse;
022import static org.junit.jupiter.api.Assertions.assertNotSame;
023
024import java.io.ByteArrayOutputStream;
025import java.io.DataOutputStream;
026import java.io.IOException;
027import org.apache.hadoop.hbase.testclassification.IOTests;
028import org.apache.hadoop.hbase.testclassification.SmallTests;
029import org.apache.hadoop.hbase.util.Bytes;
030import org.junit.jupiter.api.Tag;
031import org.junit.jupiter.api.Test;
032
033@Tag(IOTests.TAG)
034@Tag(SmallTests.TAG)
035public class TestImmutableBytesWritable {
036
037  @Test
038  public void testHash() throws Exception {
039    assertEquals(new ImmutableBytesWritable(Bytes.toBytes("xxabc"), 2, 3).hashCode(),
040      new ImmutableBytesWritable(Bytes.toBytes("abc")).hashCode());
041    assertEquals(new ImmutableBytesWritable(Bytes.toBytes("xxabcd"), 2, 3).hashCode(),
042      new ImmutableBytesWritable(Bytes.toBytes("abc")).hashCode());
043    assertNotSame(new ImmutableBytesWritable(Bytes.toBytes("xxabc"), 2, 3).hashCode(),
044      new ImmutableBytesWritable(Bytes.toBytes("xxabc"), 2, 2).hashCode());
045  }
046
047  @Test
048  public void testSpecificCompare() {
049    ImmutableBytesWritable ibw1 = new ImmutableBytesWritable(new byte[] { 0x0f });
050    ImmutableBytesWritable ibw2 = new ImmutableBytesWritable(new byte[] { 0x00, 0x00 });
051    ImmutableBytesWritable.Comparator c = new ImmutableBytesWritable.Comparator();
052    assertFalse(c.compare(ibw1, ibw2) < 0, "ibw1 < ibw2");
053  }
054
055  @Test
056  public void testComparison() throws Exception {
057    runTests("aa", "b", -1);
058    runTests("aa", "aa", 0);
059    runTests("aa", "ab", -1);
060    runTests("aa", "aaa", -1);
061    runTests("", "", 0);
062    runTests("", "a", -1);
063  }
064
065  private void runTests(String aStr, String bStr, int signum) throws Exception {
066    ImmutableBytesWritable a = new ImmutableBytesWritable(Bytes.toBytes(aStr));
067    ImmutableBytesWritable b = new ImmutableBytesWritable(Bytes.toBytes(bStr));
068
069    doComparisonsOnObjects(a, b, signum);
070    doComparisonsOnRaw(a, b, signum);
071
072    // Tests for when the offset is non-zero
073    a = new ImmutableBytesWritable(Bytes.toBytes("xxx" + aStr), 3, aStr.length());
074    b = new ImmutableBytesWritable(Bytes.toBytes("yy" + bStr), 2, bStr.length());
075    doComparisonsOnObjects(a, b, signum);
076    doComparisonsOnRaw(a, b, signum);
077
078    // Tests for when offset is nonzero and length doesn't extend to end
079    a = new ImmutableBytesWritable(Bytes.toBytes("xxx" + aStr + "zzz"), 3, aStr.length());
080    b = new ImmutableBytesWritable(Bytes.toBytes("yy" + bStr + "aaa"), 2, bStr.length());
081    doComparisonsOnObjects(a, b, signum);
082    doComparisonsOnRaw(a, b, signum);
083  }
084
085  private int signum(int i) {
086    if (i > 0) return 1;
087    if (i == 0) return 0;
088    return -1;
089  }
090
091  private void doComparisonsOnRaw(ImmutableBytesWritable a, ImmutableBytesWritable b,
092    int expectedSignum) throws IOException {
093    ImmutableBytesWritable.Comparator comparator = new ImmutableBytesWritable.Comparator();
094
095    ByteArrayOutputStream baosA = new ByteArrayOutputStream();
096    ByteArrayOutputStream baosB = new ByteArrayOutputStream();
097
098    a.write(new DataOutputStream(baosA));
099    b.write(new DataOutputStream(baosB));
100
101    assertEquals(signum(comparator.compare(baosA.toByteArray(), 0, baosA.size(),
102      baosB.toByteArray(), 0, baosB.size())), expectedSignum,
103      "Comparing " + a + " and " + b + " as raw");
104
105    assertEquals(-signum(comparator.compare(baosB.toByteArray(), 0, baosB.size(),
106      baosA.toByteArray(), 0, baosA.size())), expectedSignum,
107      "Comparing " + a + " and " + b + " as raw (inverse)");
108  }
109
110  private void doComparisonsOnObjects(ImmutableBytesWritable a, ImmutableBytesWritable b,
111    int expectedSignum) {
112    ImmutableBytesWritable.Comparator comparator = new ImmutableBytesWritable.Comparator();
113    assertEquals(signum(comparator.compare(a, b)), expectedSignum,
114      "Comparing " + a + " and " + b + " as objects");
115    assertEquals(-signum(comparator.compare(b, a)), expectedSignum,
116      "Comparing " + a + " and " + b + " as objects (inverse)");
117  }
118
119}