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