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.assertTrue; 021import static org.junit.Assert.fail; 022 023import java.io.IOException; 024import org.apache.hadoop.hbase.HBaseClassTestRule; 025import org.apache.hadoop.hbase.HBaseTestingUtility; 026import org.apache.hadoop.hbase.TableName; 027import org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException; 028import org.apache.hadoop.hbase.testclassification.MediumTests; 029import org.apache.hadoop.hbase.util.Bytes; 030import org.junit.AfterClass; 031import org.junit.BeforeClass; 032import org.junit.ClassRule; 033import org.junit.Rule; 034import org.junit.Test; 035import org.junit.experimental.categories.Category; 036import org.junit.rules.TestName; 037 038@Category(MediumTests.class) 039public class TestCheckAndMutate { 040 041 @ClassRule 042 public static final HBaseClassTestRule CLASS_RULE = 043 HBaseClassTestRule.forClass(TestCheckAndMutate.class); 044 045 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 046 private static final byte[] ROWKEY = Bytes.toBytes("12345"); 047 private static final byte[] FAMILY = Bytes.toBytes("cf"); 048 049 @Rule 050 public TestName name = new TestName(); 051 052 @BeforeClass 053 public static void setUpBeforeClass() throws Exception { 054 TEST_UTIL.startMiniCluster(); 055 } 056 057 @AfterClass 058 public static void tearDownAfterClass() throws Exception { 059 TEST_UTIL.shutdownMiniCluster(); 060 } 061 062 private Table createTable() 063 throws IOException, InterruptedException { 064 final TableName tableName = TableName.valueOf(name.getMethodName()); 065 Table table = TEST_UTIL.createTable(tableName, FAMILY); 066 TEST_UTIL.waitTableAvailable(tableName.getName(), 5000); 067 return table; 068 } 069 070 private void putOneRow(Table table) throws IOException { 071 Put put = new Put(ROWKEY); 072 put.addColumn(FAMILY, Bytes.toBytes("A"), Bytes.toBytes("a")); 073 put.addColumn(FAMILY, Bytes.toBytes("B"), Bytes.toBytes("b")); 074 put.addColumn(FAMILY, Bytes.toBytes("C"), Bytes.toBytes("c")); 075 table.put(put); 076 } 077 078 private void getOneRowAndAssertAllExist(final Table table) throws IOException { 079 Get get = new Get(ROWKEY); 080 Result result = table.get(get); 081 assertTrue("Column A value should be a", 082 Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("A"))).equals("a")); 083 assertTrue("Column B value should be b", 084 Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("B"))).equals("b")); 085 assertTrue("Column C value should be c", 086 Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("C"))).equals("c")); 087 } 088 089 private void getOneRowAndAssertAllButCExist(final Table table) throws IOException { 090 Get get = new Get(ROWKEY); 091 Result result = table.get(get); 092 assertTrue("Column A value should be a", 093 Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("A"))).equals("a")); 094 assertTrue("Column B value should be b", 095 Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("B"))).equals("b")); 096 assertTrue("Column C should not exist", 097 result.getValue(FAMILY, Bytes.toBytes("C")) == null); 098 } 099 100 private RowMutations makeRowMutationsWithColumnCDeleted() throws IOException { 101 RowMutations rm = new RowMutations(ROWKEY, 2); 102 Put put = new Put(ROWKEY); 103 put.addColumn(FAMILY, Bytes.toBytes("A"), Bytes.toBytes("a")); 104 put.addColumn(FAMILY, Bytes.toBytes("B"), Bytes.toBytes("b")); 105 rm.add(put); 106 Delete del = new Delete(ROWKEY); 107 del.addColumn(FAMILY, Bytes.toBytes("C")); 108 rm.add(del); 109 return rm; 110 } 111 112 private RowMutations getBogusRowMutations() throws IOException { 113 Put p = new Put(ROWKEY); 114 byte[] value = new byte[0]; 115 p.addColumn(new byte[]{'b', 'o', 'g', 'u', 's'}, new byte[]{'A'}, value); 116 RowMutations rm = new RowMutations(ROWKEY); 117 rm.add(p); 118 return rm; 119 } 120 121 @Test 122 public void testCheckAndMutate() throws Throwable { 123 try (Table table = createTable()) { 124 // put one row 125 putOneRow(table); 126 // get row back and assert the values 127 getOneRowAndAssertAllExist(table); 128 129 // put the same row again with C column deleted 130 RowMutations rm = makeRowMutationsWithColumnCDeleted(); 131 boolean res = table.checkAndMutate(ROWKEY, FAMILY).qualifier(Bytes.toBytes("A")) 132 .ifEquals(Bytes.toBytes("a")).thenMutate(rm); 133 assertTrue(res); 134 135 // get row back and assert the values 136 getOneRowAndAssertAllButCExist(table); 137 138 //Test that we get a region level exception 139 try { 140 rm = getBogusRowMutations(); 141 table.checkAndMutate(ROWKEY, FAMILY).qualifier(Bytes.toBytes("A")) 142 .ifEquals(Bytes.toBytes("a")).thenMutate(rm); 143 fail("Expected NoSuchColumnFamilyException"); 144 } catch (RetriesExhaustedWithDetailsException e) { 145 try { 146 throw e.getCause(0); 147 } catch (NoSuchColumnFamilyException e1) { 148 // expected 149 } 150 } 151 } 152 } 153 154 @Test 155 public void testCheckAndMutateWithBuilder() throws Throwable { 156 try (Table table = createTable()) { 157 // put one row 158 putOneRow(table); 159 // get row back and assert the values 160 getOneRowAndAssertAllExist(table); 161 162 // put the same row again with C column deleted 163 RowMutations rm = makeRowMutationsWithColumnCDeleted(); 164 boolean res = table.checkAndMutate(ROWKEY, FAMILY).qualifier(Bytes.toBytes("A")) 165 .ifEquals(Bytes.toBytes("a")).thenMutate(rm); 166 assertTrue(res); 167 168 // get row back and assert the values 169 getOneRowAndAssertAllButCExist(table); 170 171 //Test that we get a region level exception 172 try { 173 rm = getBogusRowMutations(); 174 table.checkAndMutate(ROWKEY, FAMILY).qualifier(Bytes.toBytes("A")) 175 .ifEquals(Bytes.toBytes("a")).thenMutate(rm); 176 fail("Expected NoSuchColumnFamilyException"); 177 } catch (RetriesExhaustedWithDetailsException e) { 178 try { 179 throw e.getCause(0); 180 } catch (NoSuchColumnFamilyException e1) { 181 // expected 182 } 183 } 184 } 185 } 186 187}