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.client;
019
020import static org.hamcrest.MatcherAssert.assertThat;
021import static org.hamcrest.Matchers.containsString;
022import static org.junit.jupiter.api.Assertions.assertEquals;
023import static org.junit.jupiter.api.Assertions.assertNull;
024import static org.junit.jupiter.api.Assertions.assertThrows;
025import static org.junit.jupiter.api.Assertions.assertTrue;
026
027import java.io.IOException;
028import org.apache.hadoop.hbase.KeyValue;
029import org.apache.hadoop.hbase.testclassification.ClientTests;
030import org.apache.hadoop.hbase.testclassification.SmallTests;
031import org.apache.hadoop.hbase.util.Bytes;
032import org.junit.jupiter.api.Tag;
033import org.junit.jupiter.api.Test;
034
035@Tag(ClientTests.TAG)
036@Tag(SmallTests.TAG)
037public class TestClientDataStructureMisc {
038
039  @Test
040  public void testAddKeyValue() {
041    final byte[] CONTENTS_FAMILY = Bytes.toBytes("contents");
042    final byte[] value = Bytes.toBytes("abcd");
043    final byte[] row1 = Bytes.toBytes("row1");
044    final byte[] row2 = Bytes.toBytes("row2");
045    byte[] qualifier = Bytes.toBytes("qf1");
046    Put put = new Put(row1);
047
048    // Adding KeyValue with the same row
049    KeyValue kv = new KeyValue(row1, CONTENTS_FAMILY, qualifier, value);
050    boolean ok = true;
051    try {
052      put.add(kv);
053    } catch (IOException e) {
054      ok = false;
055    }
056    assertTrue(ok);
057
058    // Adding KeyValue with the different row
059    kv = new KeyValue(row2, CONTENTS_FAMILY, qualifier, value);
060    ok = false;
061    try {
062      put.add(kv);
063    } catch (IOException e) {
064      ok = true;
065    }
066    assertTrue(ok);
067  }
068
069  /**
070   * For HBASE-2156
071   */
072  @Test
073  public void testScanVariableReuse() {
074    byte[] family = Bytes.toBytes("family");
075    byte[] qual = Bytes.toBytes("qual");
076    Scan scan = new Scan();
077    scan.addFamily(family);
078    scan.addColumn(family, qual);
079
080    assertEquals(1, scan.getFamilyMap().get(family).size());
081
082    scan = new Scan();
083    scan.addFamily(family);
084
085    assertNull(scan.getFamilyMap().get(family));
086    assertTrue(scan.getFamilyMap().containsKey(family));
087  }
088
089  @Test
090  public void testNegativeTimestamp() throws IOException {
091    IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
092      () -> new Put(Bytes.toBytes("row"), -1), "Negative timestamps should not have been allowed");
093    assertThat(ex.getMessage(), containsString("negative"));
094
095    ex = assertThrows(
096      IllegalArgumentException.class, () -> new Put(Bytes.toBytes("row"))
097        .addColumn(Bytes.toBytes("f"), Bytes.toBytes("q"), -1, Bytes.toBytes("v")),
098      "Negative timestamps should not have been allowed");
099    assertThat(ex.getMessage(), containsString("negative"));
100
101    ex = assertThrows(IllegalArgumentException.class, () -> new Delete(Bytes.toBytes("row"), -1),
102      "Negative timestamps should not have been allowed");
103    assertThat(ex.getMessage(), containsString("negative"));
104
105    ex = assertThrows(IllegalArgumentException.class,
106      () -> new Delete(Bytes.toBytes("row")).addFamily(Bytes.toBytes("f"), -1),
107      "Negative timestamps should not have been allowed");
108    assertThat(ex.getMessage(), containsString("negative"));
109
110    ex = assertThrows(IllegalArgumentException.class, () -> new Scan().setTimeRange(-1, 1),
111      "Negative timestamps should not have been allowed");
112    assertThat(ex.getMessage(), containsString("negative"));
113
114    // KeyValue should allow negative timestamps for backwards compat. Otherwise, if the user
115    // already has negative timestamps in cluster data, HBase won't be able to handle that
116    new KeyValue(Bytes.toBytes(42), Bytes.toBytes(42), Bytes.toBytes(42), -1, Bytes.toBytes(42));
117  }
118}