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.constraint; 019 020import static org.junit.Assert.assertFalse; 021import static org.junit.Assert.assertTrue; 022import static org.junit.Assert.fail; 023 024import org.apache.hadoop.hbase.HBaseClassTestRule; 025import org.apache.hadoop.hbase.HBaseTestingUtil; 026import org.apache.hadoop.hbase.TableName; 027import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 028import org.apache.hadoop.hbase.client.Put; 029import org.apache.hadoop.hbase.client.Table; 030import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 031import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; 032import org.apache.hadoop.hbase.testclassification.MediumTests; 033import org.apache.hadoop.hbase.testclassification.MiscTests; 034import org.apache.hadoop.hbase.util.Bytes; 035import org.junit.After; 036import org.junit.AfterClass; 037import org.junit.BeforeClass; 038import org.junit.ClassRule; 039import org.junit.Test; 040import org.junit.experimental.categories.Category; 041import org.slf4j.Logger; 042import org.slf4j.LoggerFactory; 043 044/** 045 * Do the complex testing of constraints against a minicluster 046 */ 047@Category({ MiscTests.class, MediumTests.class }) 048public class TestConstraint { 049 050 @ClassRule 051 public static final HBaseClassTestRule CLASS_RULE = 052 HBaseClassTestRule.forClass(TestConstraint.class); 053 054 private static final Logger LOG = LoggerFactory.getLogger(TestConstraint.class); 055 056 private static HBaseTestingUtil util; 057 private static final TableName tableName = TableName.valueOf("test"); 058 private static final byte[] dummy = Bytes.toBytes("dummy"); 059 private static final byte[] row1 = Bytes.toBytes("r1"); 060 private static final byte[] test = Bytes.toBytes("test"); 061 062 @BeforeClass 063 public static void setUpBeforeClass() throws Exception { 064 util = new HBaseTestingUtil(); 065 util.getConfiguration().setBoolean(CoprocessorHost.ABORT_ON_ERROR_KEY, false); 066 util.startMiniCluster(); 067 } 068 069 /** 070 * Test that we run a passing constraint 071 */ 072 @Test 073 public void testConstraintPasses() throws Exception { 074 // create the table 075 // it would be nice if this was also a method on the util 076 TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName); 077 078 for (byte[] family : new byte[][] { dummy, test }) { 079 builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(family)); 080 } 081 // add a constraint 082 Constraints.add(builder, CheckWasRunConstraint.class); 083 084 util.getAdmin().createTable(builder.build()); 085 Table table = util.getConnection().getTable(tableName); 086 try { 087 // test that we don't fail on a valid put 088 Put put = new Put(row1); 089 byte[] value = Bytes.toBytes(Integer.toString(10)); 090 byte[] qualifier = new byte[0]; 091 put.addColumn(dummy, qualifier, value); 092 table.put(put); 093 } finally { 094 table.close(); 095 } 096 assertTrue(CheckWasRunConstraint.wasRun); 097 } 098 099 /** 100 * Test that constraints will fail properly 101 */ 102 @Test 103 public void testConstraintFails() throws Exception { 104 // create the table 105 // it would be nice if this was also a method on the util 106 TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName); 107 for (byte[] family : new byte[][] { dummy, test }) { 108 builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(family)); 109 } 110 111 // add a constraint that is sure to fail 112 Constraints.add(builder, AllFailConstraint.class); 113 114 util.getAdmin().createTable(builder.build()); 115 Table table = util.getConnection().getTable(tableName); 116 117 // test that we do fail on violation 118 Put put = new Put(row1); 119 byte[] qualifier = new byte[0]; 120 put.addColumn(dummy, qualifier, Bytes.toBytes("fail")); 121 LOG.warn("Doing put in table"); 122 try { 123 table.put(put); 124 fail("This put should not have suceeded - AllFailConstraint was not run!"); 125 } catch (ConstraintException e) { 126 // expected 127 } 128 table.close(); 129 } 130 131 /** 132 * Check that if we just disable one constraint, then 133 */ 134 @Test 135 public void testDisableConstraint() throws Exception { 136 // create the table 137 TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName); 138 // add a family to the table 139 for (byte[] family : new byte[][] { dummy, test }) { 140 builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(family)); 141 } 142 // add a constraint to make sure it others get run 143 Constraints.add(builder, CheckWasRunConstraint.class); 144 145 // Add Constraint to check 146 Constraints.add(builder, AllFailConstraint.class); 147 148 // and then disable the failing constraint 149 Constraints.disableConstraint(builder, AllFailConstraint.class); 150 151 util.getAdmin().createTable(builder.build()); 152 Table table = util.getConnection().getTable(tableName); 153 try { 154 // test that we don't fail because its disabled 155 Put put = new Put(row1); 156 byte[] qualifier = new byte[0]; 157 put.addColumn(dummy, qualifier, Bytes.toBytes("pass")); 158 table.put(put); 159 } finally { 160 table.close(); 161 } 162 assertTrue(CheckWasRunConstraint.wasRun); 163 } 164 165 /** 166 * Test that if we disable all constraints, then nothing gets run 167 */ 168 @Test 169 public void testDisableConstraints() throws Exception { 170 // create the table 171 TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName); 172 173 // add a family to the table 174 for (byte[] family : new byte[][] { dummy, test }) { 175 builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(family)); 176 } 177 // add a constraint to check to see if is run 178 Constraints.add(builder, CheckWasRunConstraint.class); 179 180 // then disable all the constraints 181 Constraints.disable(builder); 182 183 util.getAdmin().createTable(builder.build()); 184 Table table = util.getConnection().getTable(tableName); 185 try { 186 // test that we do fail on violation 187 Put put = new Put(row1); 188 byte[] qualifier = new byte[0]; 189 put.addColumn(dummy, qualifier, Bytes.toBytes("pass")); 190 LOG.warn("Doing put in table"); 191 table.put(put); 192 } finally { 193 table.close(); 194 } 195 assertFalse(CheckWasRunConstraint.wasRun); 196 } 197 198 /** 199 * Check to make sure a constraint is unloaded when it fails 200 */ 201 @Test 202 public void testIsUnloaded() throws Exception { 203 // create the table 204 TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName); 205 206 // add a family to the table 207 for (byte[] family : new byte[][] { dummy, test }) { 208 builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(family)); 209 } 210 // make sure that constraints are unloaded 211 Constraints.add(builder, RuntimeFailConstraint.class); 212 // add a constraint to check to see if is run 213 Constraints.add(builder, CheckWasRunConstraint.class); 214 CheckWasRunConstraint.wasRun = false; 215 216 util.getAdmin().createTable(builder.build()); 217 Table table = util.getConnection().getTable(tableName); 218 219 // test that we do fail on violation 220 Put put = new Put(row1); 221 byte[] qualifier = new byte[0]; 222 put.addColumn(dummy, qualifier, Bytes.toBytes("pass")); 223 224 try { 225 table.put(put); 226 fail("RuntimeFailConstraint wasn't triggered - this put shouldn't work!"); 227 } catch (Exception e) {// NOOP 228 } 229 230 // try the put again, this time constraints are not used, so it works 231 table.put(put); 232 // and we make sure that constraints were not run... 233 assertFalse(CheckWasRunConstraint.wasRun); 234 table.close(); 235 } 236 237 @After 238 public void cleanup() throws Exception { 239 // cleanup 240 CheckWasRunConstraint.wasRun = false; 241 util.getAdmin().disableTable(tableName); 242 util.getAdmin().deleteTable(tableName); 243 } 244 245 @AfterClass 246 public static void tearDownAfterClass() throws Exception { 247 util.shutdownMiniCluster(); 248 } 249 250 /** 251 * Constraint to check that it was actually run (or not) 252 */ 253 public static class CheckWasRunConstraint extends BaseConstraint { 254 public static boolean wasRun = false; 255 256 @Override 257 public void check(Put p) { 258 wasRun = true; 259 } 260 } 261 262}