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.assertEquals; 021import static org.junit.jupiter.api.Assertions.assertThrows; 022import static org.junit.jupiter.api.Assertions.assertTrue; 023 024import java.io.IOException; 025import java.util.Arrays; 026import java.util.ConcurrentModificationException; 027import org.apache.hadoop.hbase.Cell; 028import org.apache.hadoop.hbase.CellScanner; 029import org.apache.hadoop.hbase.CellUtil; 030import org.apache.hadoop.hbase.KeyValue; 031import org.apache.hadoop.hbase.testclassification.ClientTests; 032import org.apache.hadoop.hbase.testclassification.SmallTests; 033import org.apache.hadoop.hbase.util.Bytes; 034import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 035import org.junit.jupiter.api.Tag; 036import org.junit.jupiter.api.Test; 037 038/** 039 * Test that I can Iterate Client Actions that hold Cells (Get does not have Cells). 040 */ 041@Tag(SmallTests.TAG) 042@Tag(ClientTests.TAG) 043public class TestPutDeleteEtcCellIteration { 044 045 private static final byte[] ROW = new byte[] { 'r' }; 046 private static final long TIMESTAMP = EnvironmentEdgeManager.currentTime(); 047 private static final int COUNT = 10; 048 049 @Test 050 public void testPutIteration() throws IOException { 051 Put p = new Put(ROW); 052 for (int i = 0; i < COUNT; i++) { 053 byte[] bytes = Bytes.toBytes(i); 054 p.addColumn(bytes, bytes, TIMESTAMP, bytes); 055 } 056 int index = 0; 057 for (CellScanner cellScanner = p.cellScanner(); cellScanner.advance();) { 058 Cell cell = cellScanner.current(); 059 byte[] bytes = Bytes.toBytes(index++); 060 assertEquals(new KeyValue(ROW, bytes, bytes, TIMESTAMP, bytes), cell); 061 } 062 assertEquals(COUNT, index); 063 } 064 065 @Test 066 public void testPutConcurrentModificationOnIteration() throws IOException { 067 Put p = new Put(ROW); 068 for (int i = 0; i < COUNT; i++) { 069 byte[] bytes = Bytes.toBytes(i); 070 p.addColumn(bytes, bytes, TIMESTAMP, bytes); 071 } 072 assertThrows(ConcurrentModificationException.class, () -> { 073 int index = 0; 074 for (CellScanner cellScanner = p.cellScanner(); cellScanner.advance();) { 075 Cell cell = cellScanner.current(); 076 byte[] bytes = Bytes.toBytes(index++); 077 // When we hit the trigger, try inserting a new KV; should trigger exception 078 p.addColumn(bytes, bytes, TIMESTAMP, bytes); 079 assertEquals(new KeyValue(ROW, bytes, bytes, TIMESTAMP, bytes), cell); 080 } 081 }); 082 } 083 084 @Test 085 public void testDeleteIteration() throws IOException { 086 Delete d = new Delete(ROW); 087 for (int i = 0; i < COUNT; i++) { 088 byte[] bytes = Bytes.toBytes(i); 089 d.addColumn(bytes, bytes, TIMESTAMP); 090 } 091 int index = 0; 092 for (CellScanner cellScanner = d.cellScanner(); cellScanner.advance();) { 093 Cell cell = cellScanner.current(); 094 byte[] bytes = Bytes.toBytes(index++); 095 assertEquals(new KeyValue(ROW, bytes, bytes, TIMESTAMP, KeyValue.Type.Delete), cell); 096 } 097 assertEquals(COUNT, index); 098 } 099 100 @Test 101 public void testAppendIteration() throws IOException { 102 Append a = new Append(ROW); 103 for (int i = 0; i < COUNT; i++) { 104 byte[] bytes = Bytes.toBytes(i); 105 a.addColumn(bytes, bytes, bytes); 106 } 107 int index = 0; 108 for (CellScanner cellScanner = a.cellScanner(); cellScanner.advance();) { 109 Cell cell = cellScanner.current(); 110 byte[] bytes = Bytes.toBytes(index++); 111 KeyValue kv = (KeyValue) cell; 112 assertTrue(Bytes.equals(CellUtil.cloneFamily(kv), bytes)); 113 assertTrue(Bytes.equals(CellUtil.cloneValue(kv), bytes)); 114 } 115 assertEquals(COUNT, index); 116 } 117 118 @Test 119 public void testIncrementIteration() throws IOException { 120 Increment increment = new Increment(ROW); 121 for (int i = 0; i < COUNT; i++) { 122 byte[] bytes = Bytes.toBytes(i); 123 increment.addColumn(bytes, bytes, i); 124 } 125 int index = 0; 126 for (CellScanner cellScanner = increment.cellScanner(); cellScanner.advance();) { 127 Cell cell = cellScanner.current(); 128 int value = index; 129 byte[] bytes = Bytes.toBytes(index++); 130 KeyValue kv = (KeyValue) cell; 131 assertTrue(Bytes.equals(CellUtil.cloneFamily(kv), bytes)); 132 long a = Bytes.toLong(CellUtil.cloneValue(kv)); 133 assertEquals(value, a); 134 } 135 assertEquals(COUNT, index); 136 } 137 138 @Test 139 public void testResultIteration() throws IOException { 140 Cell[] cells = new Cell[COUNT]; 141 for (int i = 0; i < COUNT; i++) { 142 byte[] bytes = Bytes.toBytes(i); 143 cells[i] = new KeyValue(ROW, bytes, bytes, TIMESTAMP, bytes); 144 } 145 Result r = Result.create(Arrays.asList(cells)); 146 int index = 0; 147 for (CellScanner cellScanner = r.cellScanner(); cellScanner.advance();) { 148 Cell cell = cellScanner.current(); 149 byte[] bytes = Bytes.toBytes(index++); 150 assertEquals(new KeyValue(ROW, bytes, bytes, TIMESTAMP, bytes), cell); 151 } 152 assertEquals(COUNT, index); 153 } 154}