View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.constraint;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertFalse;
22  import static org.junit.Assert.assertTrue;
23  import static org.junit.Assert.fail;
24  
25  import java.util.List;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.hadoop.hbase.HBaseTestingUtility;
30  import org.apache.hadoop.hbase.HColumnDescriptor;
31  import org.apache.hadoop.hbase.HTableDescriptor;
32  import org.apache.hadoop.hbase.MediumTests;
33  import org.apache.hadoop.hbase.TableName;
34  import org.apache.hadoop.hbase.client.HTable;
35  import org.apache.hadoop.hbase.client.Put;
36  import org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException;
37  import org.apache.hadoop.hbase.util.Bytes;
38  import org.junit.After;
39  import org.junit.AfterClass;
40  import org.junit.BeforeClass;
41  import org.junit.Test;
42  import org.junit.experimental.categories.Category;
43  
44  /**
45   * Do the complex testing of constraints against a minicluster
46   */
47  @Category(MediumTests.class)
48  public class TestConstraint {
49    private static final Log LOG = LogFactory
50        .getLog(TestConstraint.class);
51  
52    private static HBaseTestingUtility util;
53    private static final byte[] tableName = Bytes.toBytes("test");
54    private static final byte[] dummy = Bytes.toBytes("dummy");
55    private static final byte[] row1 = Bytes.toBytes("r1");
56    private static final byte[] test = Bytes.toBytes("test");
57  
58    @BeforeClass
59    public static void setUpBeforeClass() throws Exception {
60      util = new HBaseTestingUtility();
61      util.startMiniCluster();
62    }
63  
64    /**
65     * Test that we run a passing constraint
66     * @throws Exception
67     */
68    @SuppressWarnings("unchecked")
69    @Test
70    public void testConstraintPasses() throws Exception {
71      // create the table
72      // it would be nice if this was also a method on the util
73      HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
74      for (byte[] family : new byte[][] { dummy, test }) {
75        desc.addFamily(new HColumnDescriptor(family));
76      }
77      // add a constraint
78      Constraints.add(desc, CheckWasRunConstraint.class);
79  
80      util.getHBaseAdmin().createTable(desc);
81      HTable table = new HTable(util.getConfiguration(), tableName);
82      table.setAutoFlush(true);
83  
84      // test that we don't fail on a valid put
85      Put put = new Put(row1);
86      byte[] value = Integer.toString(10).getBytes();
87      put.add(dummy, new byte[0], value);
88      table.put(put);
89  
90      assertTrue(CheckWasRunConstraint.wasRun);
91    }
92  
93    /**
94     * Test that constraints will fail properly
95     * @throws Exception
96     */
97    @SuppressWarnings("unchecked")
98    @Test(timeout = 60000)
99    public void testConstraintFails() throws Exception {
100 
101     // create the table
102     // it would be nice if this was also a method on the util
103     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
104     for (byte[] family : new byte[][] { dummy, test }) {
105       desc.addFamily(new HColumnDescriptor(family));
106     }
107 
108     // add a constraint that is sure to fail
109     Constraints.add(desc, AllFailConstraint.class);
110 
111     util.getHBaseAdmin().createTable(desc);
112     HTable table = new HTable(util.getConfiguration(), tableName);
113     table.setAutoFlush(true);
114 
115     // test that we do fail on violation
116     Put put = new Put(row1);
117     put.add(dummy, new byte[0], "fail".getBytes());
118     LOG.warn("Doing put in table");
119     try {
120       table.put(put);
121       fail("This put should not have suceeded - AllFailConstraint was not run!");
122     } catch (RetriesExhaustedWithDetailsException e) {
123       List<Throwable> causes = e.getCauses();
124       assertEquals(
125           "More than one failure cause - should only be the failure constraint exception",
126           1, causes.size());
127       Throwable t = causes.get(0);
128       assertEquals(ConstraintException.class, t.getClass());
129     }
130     table.close();
131   }
132 
133   /**
134    * Check that if we just disable one constraint, then
135    * @throws Throwable
136    */
137   @SuppressWarnings("unchecked")
138   @Test
139   public void testDisableConstraint() throws Throwable {
140     // create the table
141     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
142     // add a family to the table
143     for (byte[] family : new byte[][] { dummy, test }) {
144       desc.addFamily(new HColumnDescriptor(family));
145     }
146     // add a constraint to make sure it others get run
147     Constraints.add(desc, CheckWasRunConstraint.class);
148 
149     // Add Constraint to check
150     Constraints.add(desc, AllFailConstraint.class);
151 
152     // and then disable the failing constraint
153     Constraints.disableConstraint(desc, AllFailConstraint.class);
154 
155     util.getHBaseAdmin().createTable(desc);
156     HTable table = new HTable(util.getConfiguration(), tableName);
157     table.setAutoFlush(true);
158 
159     // test that we don't fail because its disabled
160     Put put = new Put(row1);
161     put.add(dummy, new byte[0], "pass".getBytes());
162     table.put(put);
163 
164     assertTrue(CheckWasRunConstraint.wasRun);
165   }
166 
167   /**
168    * Test that if we disable all constraints, then nothing gets run
169    * @throws Throwable
170    */
171   @SuppressWarnings("unchecked")
172   @Test
173   public void testDisableConstraints() throws Throwable {
174     // create the table
175     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
176     // add a family to the table
177     for (byte[] family : new byte[][] { dummy, test }) {
178       desc.addFamily(new HColumnDescriptor(family));
179     }
180     // add a constraint to check to see if is run
181     Constraints.add(desc, CheckWasRunConstraint.class);
182 
183     // then disable all the constraints
184     Constraints.disable(desc);
185 
186     util.getHBaseAdmin().createTable(desc);
187     HTable table = new HTable(util.getConfiguration(), tableName);
188     table.setAutoFlush(true);
189 
190     // test that we do fail on violation
191     Put put = new Put(row1);
192     put.add(dummy, new byte[0], "pass".getBytes());
193     LOG.warn("Doing put in table");
194     table.put(put);
195 
196     assertFalse(CheckWasRunConstraint.wasRun);
197   }
198 
199   /**
200    * Check to make sure a constraint is unloaded when it fails
201    * @throws Exception
202    */
203   @Test
204   public void testIsUnloaded() throws Exception {
205     // create the table
206     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
207     // add a family to the table
208     for (byte[] family : new byte[][] { dummy, test }) {
209       desc.addFamily(new HColumnDescriptor(family));
210     }
211     // make sure that constraints are unloaded
212     Constraints.add(desc, RuntimeFailConstraint.class);
213     // add a constraint to check to see if is run
214     Constraints.add(desc, CheckWasRunConstraint.class);
215     CheckWasRunConstraint.wasRun = false;
216 
217     util.getHBaseAdmin().createTable(desc);
218     HTable table = new HTable(util.getConfiguration(), tableName);
219     table.setAutoFlush(true);
220 
221     // test that we do fail on violation
222     Put put = new Put(row1);
223     put.add(dummy, new byte[0], "pass".getBytes());
224     
225     try{
226     table.put(put);
227     fail("RuntimeFailConstraint wasn't triggered - this put shouldn't work!");
228     } catch (Exception e) {// NOOP
229     }
230 
231     // try the put again, this time constraints are not used, so it works
232     table.put(put);
233     // and we make sure that constraints were not run...
234     assertFalse(CheckWasRunConstraint.wasRun);
235     table.close();
236   }
237 
238   @After
239   public void cleanup() throws Exception {
240     // cleanup
241     CheckWasRunConstraint.wasRun = false;
242     util.getHBaseAdmin().disableTable(tableName);
243     util.getHBaseAdmin().deleteTable(tableName);
244   }
245 
246   @AfterClass
247   public static void tearDownAfterClass() throws Exception {
248     util.shutdownMiniCluster();
249   }
250 
251   /**
252    * Constraint to check that it was actually run (or not)
253    */
254   public static class CheckWasRunConstraint extends BaseConstraint {
255     public static boolean wasRun = false;
256 
257     @Override
258     public void check(Put p) {
259       wasRun = true;
260     }
261   }
262 
263 }