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.junit.jupiter.api.Assertions.assertNotEquals; 021import static org.junit.jupiter.api.Assertions.assertTrue; 022 023import java.io.IOException; 024import java.util.List; 025import org.apache.hadoop.hbase.Cell; 026import org.apache.hadoop.hbase.CellBuilderFactory; 027import org.apache.hadoop.hbase.CellBuilderType; 028import org.apache.hadoop.hbase.CellUtil; 029import org.apache.hadoop.hbase.ExtendedCell; 030import org.apache.hadoop.hbase.PrivateCellUtil; 031import org.apache.hadoop.hbase.io.TimeRange; 032import org.apache.hadoop.hbase.testclassification.ClientTests; 033import org.apache.hadoop.hbase.testclassification.SmallTests; 034import org.apache.hadoop.hbase.util.Bytes; 035import org.junit.jupiter.api.Assertions; 036import org.junit.jupiter.api.Tag; 037import org.junit.jupiter.api.Test; 038 039@Tag(SmallTests.TAG) 040@Tag(ClientTests.TAG) 041public class TestMutation { 042 043 @Test 044 public void testAppendCopyConstructor() throws IOException { 045 Append origin = new Append(Bytes.toBytes("ROW-01")); 046 origin.setPriority(100); 047 byte[] family = Bytes.toBytes("CF-01"); 048 049 origin.add(CellBuilderFactory.create(CellBuilderType.SHALLOW_COPY).setRow(origin.getRow()) 050 .setFamily(family).setQualifier(Bytes.toBytes("q")).setType(Cell.Type.Put) 051 .setValue(Bytes.toBytes(100)).build()); 052 origin.addColumn(family, Bytes.toBytes("q0"), Bytes.toBytes("value")); 053 origin.setTimeRange(100, 1000); 054 Append clone = new Append(origin); 055 assertEquals(origin, clone); 056 origin.addColumn(family, Bytes.toBytes("q1"), Bytes.toBytes("value")); 057 058 // They should have different cell lists 059 assertNotEquals(origin.getCellList(family), clone.getCellList(family)); 060 } 061 062 @Test 063 public void testIncrementCopyConstructor() throws IOException { 064 Increment origin = new Increment(Bytes.toBytes("ROW-01")); 065 origin.setPriority(100); 066 byte[] family = Bytes.toBytes("CF-01"); 067 068 origin.add(CellBuilderFactory.create(CellBuilderType.SHALLOW_COPY).setRow(origin.getRow()) 069 .setFamily(family).setQualifier(Bytes.toBytes("q")).setType(Cell.Type.Put) 070 .setValue(Bytes.toBytes(100)).build()); 071 origin.addColumn(family, Bytes.toBytes("q0"), 4); 072 origin.setTimeRange(100, 1000); 073 Increment clone = new Increment(origin); 074 assertEquals(origin, clone); 075 origin.addColumn(family, Bytes.toBytes("q1"), 3); 076 077 // They should have different cell lists 078 assertNotEquals(origin.getCellList(family), clone.getCellList(family)); 079 } 080 081 @Test 082 public void testDeleteCopyConstructor() throws IOException { 083 Delete origin = new Delete(Bytes.toBytes("ROW-01")); 084 origin.setPriority(100); 085 byte[] family = Bytes.toBytes("CF-01"); 086 087 origin.add(CellBuilderFactory.create(CellBuilderType.SHALLOW_COPY).setRow(origin.getRow()) 088 .setFamily(family).setQualifier(Bytes.toBytes("q")).setType(Cell.Type.Delete).build()); 089 origin.addColumn(family, Bytes.toBytes("q0")); 090 origin.addColumns(family, Bytes.toBytes("q1")); 091 origin.addFamily(family); 092 origin.addColumns(family, Bytes.toBytes("q2"), 100); 093 origin.addFamilyVersion(family, 1000); 094 Delete clone = new Delete(origin); 095 assertEquals(origin, clone); 096 origin.addColumn(family, Bytes.toBytes("q3")); 097 098 // They should have different cell lists 099 assertNotEquals(origin.getCellList(family), clone.getCellList(family)); 100 } 101 102 @Test 103 public void testPutCopyConstructor() throws IOException { 104 Put origin = new Put(Bytes.toBytes("ROW-01")); 105 origin.setPriority(100); 106 byte[] family = Bytes.toBytes("CF-01"); 107 108 origin.add(CellBuilderFactory.create(CellBuilderType.SHALLOW_COPY).setRow(origin.getRow()) 109 .setFamily(family).setQualifier(Bytes.toBytes("q")).setType(Cell.Type.Put) 110 .setValue(Bytes.toBytes("value")).build()); 111 origin.addColumn(family, Bytes.toBytes("q0"), Bytes.toBytes("V-01")); 112 origin.addColumn(family, Bytes.toBytes("q1"), 100, Bytes.toBytes("V-01")); 113 Put clone = new Put(origin); 114 assertEquals(origin, clone); 115 origin.addColumn(family, Bytes.toBytes("q2"), Bytes.toBytes("V-02")); 116 117 // They should have different cell lists 118 assertNotEquals(origin.getCellList(family), clone.getCellList(family)); 119 } 120 121 private void assertEquals(Mutation origin, Mutation clone) { 122 Assertions.assertEquals(origin.getFamilyCellMap().size(), clone.getFamilyCellMap().size()); 123 for (byte[] family : origin.getFamilyCellMap().keySet()) { 124 List<ExtendedCell> originCells = origin.getCellList(family); 125 List<ExtendedCell> cloneCells = clone.getCellList(family); 126 Assertions.assertEquals(originCells.size(), cloneCells.size()); 127 for (int i = 0; i != cloneCells.size(); ++i) { 128 ExtendedCell originCell = originCells.get(i); 129 ExtendedCell cloneCell = cloneCells.get(i); 130 assertTrue(PrivateCellUtil.equals(originCell, cloneCell)); 131 assertTrue(CellUtil.matchingValue(originCell, cloneCell)); 132 } 133 } 134 Assertions.assertEquals(origin.getAttributesMap().size(), clone.getAttributesMap().size()); 135 for (String name : origin.getAttributesMap().keySet()) { 136 byte[] originValue = origin.getAttributesMap().get(name); 137 byte[] cloneValue = clone.getAttributesMap().get(name); 138 assertTrue(Bytes.equals(originValue, cloneValue)); 139 } 140 Assertions.assertEquals(origin.getTimestamp(), clone.getTimestamp()); 141 Assertions.assertEquals(origin.getPriority(), clone.getPriority()); 142 if (origin instanceof Append) { 143 assertEquals(((Append) origin).getTimeRange(), ((Append) clone).getTimeRange()); 144 } 145 if (origin instanceof Increment) { 146 assertEquals(((Increment) origin).getTimeRange(), ((Increment) clone).getTimeRange()); 147 } 148 } 149 150 private static void assertEquals(TimeRange origin, TimeRange clone) { 151 Assertions.assertEquals(origin.getMin(), clone.getMin()); 152 Assertions.assertEquals(origin.getMax(), clone.getMax()); 153 } 154 155 // HBASE-14881 156 @Test 157 public void testRowIsImmutableOrNot() { 158 byte[] rowKey = Bytes.toBytes("immutable"); 159 160 // Test when row key is immutable 161 Put putRowIsImmutable = new Put(rowKey, true); 162 assertTrue(rowKey == putRowIsImmutable.getRow()); // No local copy is made 163 164 // Test when row key is not immutable 165 Put putRowIsNotImmutable = new Put(rowKey, 1000L, false); 166 assertTrue(rowKey != putRowIsNotImmutable.getRow()); // A local copy is made 167 } 168 169 // HBASE-14882 170 @Test 171 public void testAddImmutableToPut() throws IOException { 172 byte[] row = Bytes.toBytes("immutable-row"); 173 byte[] family = Bytes.toBytes("immutable-family"); 174 175 byte[] qualifier0 = Bytes.toBytes("immutable-qualifier-0"); 176 byte[] value0 = Bytes.toBytes("immutable-value-0"); 177 178 byte[] qualifier1 = Bytes.toBytes("immutable-qualifier-1"); 179 byte[] value1 = Bytes.toBytes("immutable-value-1"); 180 long ts1 = 5000L; 181 182 // "true" indicates that the input row is immutable 183 Put put = new Put(row, true); 184 put 185 .add(CellBuilderFactory.create(CellBuilderType.SHALLOW_COPY).setRow(row).setFamily(family) 186 .setQualifier(qualifier0).setTimestamp(put.getTimestamp()).setType(Cell.Type.Put) 187 .setValue(value0).build()) 188 .add(CellBuilderFactory.create(CellBuilderType.SHALLOW_COPY).setRow(row).setFamily(family) 189 .setQualifier(qualifier1).setTimestamp(ts1).setType(Cell.Type.Put).setValue(value1) 190 .build()); 191 192 // Verify the cell of family:qualifier0 193 Cell cell0 = put.get(family, qualifier0).get(0); 194 195 // Verify no local copy is made for family, qualifier or value 196 assertTrue(cell0.getFamilyArray() == family); 197 assertTrue(cell0.getQualifierArray() == qualifier0); 198 assertTrue(cell0.getValueArray() == value0); 199 200 // Verify timestamp 201 assertTrue(cell0.getTimestamp() == put.getTimestamp()); 202 203 // Verify the cell of family:qualifier1 204 Cell cell1 = put.get(family, qualifier1).get(0); 205 206 // Verify no local copy is made for family, qualifier or value 207 assertTrue(cell1.getFamilyArray() == family); 208 assertTrue(cell1.getQualifierArray() == qualifier1); 209 assertTrue(cell1.getValueArray() == value1); 210 211 // Verify timestamp 212 assertTrue(cell1.getTimestamp() == ts1); 213 } 214}