/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.hbase.client;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.TableNameTestRule;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.testclassification.ClientTests;
import org.apache.hadoop.hbase.testclassification.SmallTests;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
import org.apache.hadoop.hbase.util.MD5Hash;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;

import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;

@Category({ ClientTests.class, SmallTests.class })
public class TestRegionInfoBuilder {

  @ClassRule
  public static final HBaseClassTestRule CLASS_RULE =
    HBaseClassTestRule.forClass(TestRegionInfoBuilder.class);

  @Rule
  public TableNameTestRule name = new TableNameTestRule();

  @Test
  public void testBuilder() {
    TableName tn = TableName.valueOf("test");
    RegionInfoBuilder builder = RegionInfoBuilder.newBuilder(tn);
    byte[] startKey = Bytes.toBytes("a");
    builder.setStartKey(startKey);
    byte[] endKey = Bytes.toBytes("z");
    builder.setEndKey(endKey);
    int regionId = 1;
    builder.setRegionId(1);
    int replicaId = 2;
    builder.setReplicaId(replicaId);
    boolean offline = true;
    builder.setOffline(offline);
    boolean isSplit = true;
    builder.setSplit(isSplit);
    RegionInfo ri = builder.build();

    assertEquals(tn, ri.getTable());
    assertArrayEquals(startKey, ri.getStartKey());
    assertArrayEquals(endKey, ri.getEndKey());
    assertEquals(regionId, ri.getRegionId());
    assertEquals(replicaId, ri.getReplicaId());
    assertEquals(offline, ri.isOffline());
    assertEquals(isSplit, ri.isSplit());
  }

  @Test
  public void testPb() throws DeserializationException {
    RegionInfo ri = RegionInfoBuilder.FIRST_META_REGIONINFO;
    byte[] bytes = RegionInfo.toByteArray(ri);
    RegionInfo pbri = RegionInfo.parseFrom(bytes);
    assertTrue(RegionInfo.COMPARATOR.compare(ri, pbri) == 0);
  }

  @Test
  public void testCreateRegionInfoName() throws Exception {
    final TableName tn = name.getTableName();
    String startKey = "startkey";
    final byte[] sk = Bytes.toBytes(startKey);
    String id = "id";

    // old format region name
    byte[] name = RegionInfo.createRegionName(tn, sk, id, false);
    String nameStr = Bytes.toString(name);
    assertEquals(tn + "," + startKey + "," + id, nameStr);

    // new format region name.
    String md5HashInHex = MD5Hash.getMD5AsHex(name);
    assertEquals(RegionInfo.MD5_HEX_LENGTH, md5HashInHex.length());
    name = RegionInfo.createRegionName(tn, sk, id, true);
    nameStr = Bytes.toString(name);
    assertEquals(tn + "," + startKey + "," + id + "." + md5HashInHex + ".", nameStr);
  }

  @Test
  public void testContainsRange() {
    TableDescriptor tableDesc = TableDescriptorBuilder.newBuilder(name.getTableName()).build();
    RegionInfo ri = RegionInfoBuilder.newBuilder(tableDesc.getTableName())
      .setStartKey(Bytes.toBytes("a")).setEndKey(Bytes.toBytes("g")).build();
    // Single row range at start of region
    assertTrue(ri.containsRange(Bytes.toBytes("a"), Bytes.toBytes("a")));
    // Fully contained range
    assertTrue(ri.containsRange(Bytes.toBytes("b"), Bytes.toBytes("c")));
    // Range overlapping start of region
    assertTrue(ri.containsRange(Bytes.toBytes("a"), Bytes.toBytes("c")));
    // Fully contained single-row range
    assertTrue(ri.containsRange(Bytes.toBytes("c"), Bytes.toBytes("c")));
    // Range that overlaps end key and hence doesn't fit
    assertFalse(ri.containsRange(Bytes.toBytes("a"), Bytes.toBytes("g")));
    // Single row range on end key
    assertFalse(ri.containsRange(Bytes.toBytes("g"), Bytes.toBytes("g")));
    // Single row range entirely outside
    assertFalse(ri.containsRange(Bytes.toBytes("z"), Bytes.toBytes("z")));

    // Degenerate range
    try {
      ri.containsRange(Bytes.toBytes("z"), Bytes.toBytes("a"));
      fail("Invalid range did not throw IAE");
    } catch (IllegalArgumentException iae) {
    }
  }

  @Test
  public void testContainsRangeForMetaTable() {
    TableDescriptor tableDesc =
        TableDescriptorBuilder.newBuilder(TableName.META_TABLE_NAME).build();
    RegionInfo hri = RegionInfoBuilder.newBuilder(tableDesc.getTableName()).build();
    byte[] startRow = HConstants.EMPTY_START_ROW;
    byte[] row1 = Bytes.toBytes("a,a,0");
    byte[] row2 = Bytes.toBytes("aaaaa,,1");
    byte[] row3 = Bytes.toBytes("aaaaa,\u0000\u0000,2");
    byte[] row4 = Bytes.toBytes("aaaaa,\u0001,3");
    byte[] row5 = Bytes.toBytes("aaaaa,a,4");
    byte[] row6 = Bytes.toBytes("aaaaa,\u1000,5");

    // Single row range at start of region
    assertTrue(hri.containsRange(startRow, startRow));
    // Fully contained range
    assertTrue(hri.containsRange(row1, row2));
    assertTrue(hri.containsRange(row2, row3));
    assertTrue(hri.containsRange(row3, row4));
    assertTrue(hri.containsRange(row4, row5));
    assertTrue(hri.containsRange(row5, row6));
    // Range overlapping start of region
    assertTrue(hri.containsRange(startRow, row2));
    // Fully contained single-row range
    assertTrue(hri.containsRange(row1, row1));
    // Degenerate range
    try {
      hri.containsRange(row3, row2);
      fail("Invalid range did not throw IAE");
    } catch (IllegalArgumentException iae) {
    }
  }

  @Test
  public void testLastRegionCompare() {
    TableDescriptor tableDesc = TableDescriptorBuilder.newBuilder(name.getTableName()).build();
    RegionInfo rip = RegionInfoBuilder.newBuilder(tableDesc.getTableName())
      .setStartKey(Bytes.toBytes("a")).setEndKey(new byte[0]).build();
    RegionInfo ric = RegionInfoBuilder.newBuilder(tableDesc.getTableName())
      .setStartKey(Bytes.toBytes("a")).setEndKey(Bytes.toBytes("b")).build();
    assertTrue(RegionInfo.COMPARATOR.compare(rip, ric) > 0);
  }

  @Test
  public void testMetaTables() {
    assertTrue(RegionInfoBuilder.FIRST_META_REGIONINFO.isMetaRegion());
  }

  @Test
  public void testComparator() {
    final TableName tableName = name.getTableName();
    byte[] empty = new byte[0];
    RegionInfo older = RegionInfoBuilder.newBuilder(tableName).setStartKey(empty).setEndKey(empty)
      .setSplit(false).setRegionId(0L).build();
    RegionInfo newer = RegionInfoBuilder.newBuilder(tableName).setStartKey(empty).setEndKey(empty)
      .setSplit(false).setRegionId(1L).build();
    assertTrue(RegionInfo.COMPARATOR.compare(older, newer) < 0);
    assertTrue(RegionInfo.COMPARATOR.compare(newer, older) > 0);
    assertTrue(RegionInfo.COMPARATOR.compare(older, older) == 0);
    assertTrue(RegionInfo.COMPARATOR.compare(newer, newer) == 0);
  }

  @Test
  public void testRegionNameForRegionReplicas() throws Exception {
    final TableName tn = name.getTableName();
    String startKey = "startkey";
    final byte[] sk = Bytes.toBytes(startKey);
    String id = "id";

    // assert with only the region name without encoding

    // primary, replicaId = 0
    byte[] name = RegionInfo.createRegionName(tn, sk, Bytes.toBytes(id), 0, false);
    String nameStr = Bytes.toString(name);
    assertEquals(tn + "," + startKey + "," + id, nameStr);

    // replicaId = 1
    name = RegionInfo.createRegionName(tn, sk, Bytes.toBytes(id), 1, false);
    nameStr = Bytes.toString(name);
    assertEquals(
      tn + "," + startKey + "," + id + "_" + String.format(RegionInfo.REPLICA_ID_FORMAT, 1),
      nameStr);

    // replicaId = max
    name = RegionInfo.createRegionName(tn, sk, Bytes.toBytes(id), 0xFFFF, false);
    nameStr = Bytes.toString(name);
    assertEquals(
      tn + "," + startKey + "," + id + "_" + String.format(RegionInfo.REPLICA_ID_FORMAT, 0xFFFF),
      nameStr);
  }

  @Test
  public void testParseName() throws IOException {
    final TableName tableName = name.getTableName();
    byte[] startKey = Bytes.toBytes("startKey");
    long regionId = EnvironmentEdgeManager.currentTime();
    int replicaId = 42;

    // test without replicaId
    byte[] regionName = RegionInfo.createRegionName(tableName, startKey, regionId, false);

    byte[][] fields = RegionInfo.parseRegionName(regionName);
    assertArrayEquals(Bytes.toString(fields[0]), tableName.getName(), fields[0]);
    assertArrayEquals(Bytes.toString(fields[1]), startKey, fields[1]);
    assertArrayEquals(Bytes.toString(fields[2]), Bytes.toBytes(Long.toString(regionId)), fields[2]);
    assertEquals(3, fields.length);

    // test with replicaId
    regionName = RegionInfo.createRegionName(tableName, startKey, regionId, replicaId, false);

    fields = RegionInfo.parseRegionName(regionName);
    assertArrayEquals(Bytes.toString(fields[0]), tableName.getName(), fields[0]);
    assertArrayEquals(Bytes.toString(fields[1]), startKey, fields[1]);
    assertArrayEquals(Bytes.toString(fields[2]), Bytes.toBytes(Long.toString(regionId)), fields[2]);
    assertArrayEquals(Bytes.toString(fields[3]),
      Bytes.toBytes(String.format(RegionInfo.REPLICA_ID_FORMAT, replicaId)), fields[3]);
  }

  @Test
  public void testConvert() {
    final TableName tableName =
      TableName.valueOf("ns1:" + name.getTableName().getQualifierAsString());
    byte[] startKey = Bytes.toBytes("startKey");
    byte[] endKey = Bytes.toBytes("endKey");
    boolean split = false;
    long regionId = EnvironmentEdgeManager.currentTime();
    int replicaId = 42;

    RegionInfo ri = RegionInfoBuilder.newBuilder(tableName).setStartKey(startKey).setEndKey(endKey)
      .setSplit(split).setRegionId(regionId).setReplicaId(replicaId).build();

    // convert two times, compare
    RegionInfo convertedRi = ProtobufUtil.toRegionInfo(ProtobufUtil.toRegionInfo(ri));

    assertEquals(ri, convertedRi);

    // test convert RegionInfo without replicaId
    HBaseProtos.RegionInfo info = HBaseProtos.RegionInfo.newBuilder()
      .setTableName(HBaseProtos.TableName.newBuilder()
        .setQualifier(UnsafeByteOperations.unsafeWrap(tableName.getQualifier()))
        .setNamespace(UnsafeByteOperations.unsafeWrap(tableName.getNamespace())).build())
      .setStartKey(UnsafeByteOperations.unsafeWrap(startKey))
      .setEndKey(UnsafeByteOperations.unsafeWrap(endKey)).setSplit(split).setRegionId(regionId)
      .build();

    convertedRi = ProtobufUtil.toRegionInfo(info);
    RegionInfo expectedRi = RegionInfoBuilder.newBuilder(tableName).setStartKey(startKey)
      .setEndKey(endKey).setSplit(split).setRegionId(regionId).setReplicaId(0).build();

    assertEquals(expectedRi, convertedRi);
  }

  private void assertRegionNameNotEquals(RegionInfo expected, RegionInfo actual) {
    assertNotEquals(expected.getRegionNameAsString(), actual.getRegionNameAsString());
    assertNotEquals(expected.getEncodedName(), actual.getEncodedName());
  }

  private void assertRegionNameEquals(RegionInfo expected, RegionInfo actual) {
    assertEquals(expected.getRegionNameAsString(), actual.getRegionNameAsString());
    assertEquals(expected.getEncodedName(), actual.getEncodedName());
  }

  @Test
  public void testNewBuilderWithRegionInfo() {
    RegionInfo ri = RegionInfoBuilder.newBuilder(name.getTableName()).build();
    assertEquals(ri, RegionInfoBuilder.newBuilder(ri).build());

    // make sure that the region name and encoded name are changed, see HBASE-24500 for more
    // details.
    assertRegionNameNotEquals(ri,
      RegionInfoBuilder.newBuilder(ri).setStartKey(new byte[1]).build());
    assertRegionNameNotEquals(ri,
      RegionInfoBuilder.newBuilder(ri).setRegionId(ri.getRegionId() + 1).build());
    assertRegionNameNotEquals(ri, RegionInfoBuilder.newBuilder(ri).setReplicaId(1).build());

    // these fields are not in region name
    assertRegionNameEquals(ri, RegionInfoBuilder.newBuilder(ri).setEndKey(new byte[1]).build());
    assertRegionNameEquals(ri, RegionInfoBuilder.newBuilder(ri).setSplit(true).build());
    assertRegionNameEquals(ri, RegionInfoBuilder.newBuilder(ri).setOffline(true).build());
  }
}
