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  
83      // test that we don't fail on a valid put
84      Put put = new Put(row1);
85      byte[] value = Integer.toString(10).getBytes();
86      put.add(dummy, new byte[0], value);
87      table.put(put);
88  
89      assertTrue(CheckWasRunConstraint.wasRun);
90    }
91  
92    /**
93     * Test that constraints will fail properly
94     * @throws Exception
95     */
96    @SuppressWarnings("unchecked")
97    @Test(timeout = 60000)
98    public void testConstraintFails() throws Exception {
99  
100     // create the table
101     // it would be nice if this was also a method on the util
102     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
103     for (byte[] family : new byte[][] { dummy, test }) {
104       desc.addFamily(new HColumnDescriptor(family));
105     }
106 
107     // add a constraint that is sure to fail
108     Constraints.add(desc, AllFailConstraint.class);
109 
110     util.getHBaseAdmin().createTable(desc);
111     HTable table = new HTable(util.getConfiguration(), tableName);
112 
113     // test that we do fail on violation
114     Put put = new Put(row1);
115     put.add(dummy, new byte[0], "fail".getBytes());
116     LOG.warn("Doing put in table");
117     try {
118       table.put(put);
119       fail("This put should not have suceeded - AllFailConstraint was not run!");
120     } catch (RetriesExhaustedWithDetailsException e) {
121       List<Throwable> causes = e.getCauses();
122       assertEquals(
123           "More than one failure cause - should only be the failure constraint exception",
124           1, causes.size());
125       Throwable t = causes.get(0);
126       assertEquals(ConstraintException.class, t.getClass());
127     }
128     table.close();
129   }
130 
131   /**
132    * Check that if we just disable one constraint, then
133    * @throws Throwable
134    */
135   @SuppressWarnings("unchecked")
136   @Test
137   public void testDisableConstraint() throws Throwable {
138     // create the table
139     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
140     // add a family to the table
141     for (byte[] family : new byte[][] { dummy, test }) {
142       desc.addFamily(new HColumnDescriptor(family));
143     }
144     // add a constraint to make sure it others get run
145     Constraints.add(desc, CheckWasRunConstraint.class);
146 
147     // Add Constraint to check
148     Constraints.add(desc, AllFailConstraint.class);
149 
150     // and then disable the failing constraint
151     Constraints.disableConstraint(desc, AllFailConstraint.class);
152 
153     util.getHBaseAdmin().createTable(desc);
154     HTable table = new HTable(util.getConfiguration(), tableName);
155 
156     // test that we don't fail because its disabled
157     Put put = new Put(row1);
158     put.add(dummy, new byte[0], "pass".getBytes());
159     table.put(put);
160 
161     assertTrue(CheckWasRunConstraint.wasRun);
162   }
163 
164   /**
165    * Test that if we disable all constraints, then nothing gets run
166    * @throws Throwable
167    */
168   @SuppressWarnings("unchecked")
169   @Test
170   public void testDisableConstraints() throws Throwable {
171     // create the table
172     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
173     // add a family to the table
174     for (byte[] family : new byte[][] { dummy, test }) {
175       desc.addFamily(new HColumnDescriptor(family));
176     }
177     // add a constraint to check to see if is run
178     Constraints.add(desc, CheckWasRunConstraint.class);
179 
180     // then disable all the constraints
181     Constraints.disable(desc);
182 
183     util.getHBaseAdmin().createTable(desc);
184     HTable table = new HTable(util.getConfiguration(), tableName);
185 
186     // test that we do fail on violation
187     Put put = new Put(row1);
188     put.add(dummy, new byte[0], "pass".getBytes());
189     LOG.warn("Doing put in table");
190     table.put(put);
191 
192     assertFalse(CheckWasRunConstraint.wasRun);
193   }
194 
195   /**
196    * Check to make sure a constraint is unloaded when it fails
197    * @throws Exception
198    */
199   @Test
200   public void testIsUnloaded() throws Exception {
201     // create the table
202     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
203     // add a family to the table
204     for (byte[] family : new byte[][] { dummy, test }) {
205       desc.addFamily(new HColumnDescriptor(family));
206     }
207     // make sure that constraints are unloaded
208     Constraints.add(desc, RuntimeFailConstraint.class);
209     // add a constraint to check to see if is run
210     Constraints.add(desc, CheckWasRunConstraint.class);
211     CheckWasRunConstraint.wasRun = false;
212 
213     util.getHBaseAdmin().createTable(desc);
214     HTable table = new HTable(util.getConfiguration(), tableName);
215 
216     // test that we do fail on violation
217     Put put = new Put(row1);
218     put.add(dummy, new byte[0], "pass".getBytes());
219     
220     try{
221     table.put(put);
222     fail("RuntimeFailConstraint wasn't triggered - this put shouldn't work!");
223     } catch (Exception e) {// NOOP
224     }
225 
226     // try the put again, this time constraints are not used, so it works
227     table.put(put);
228     // and we make sure that constraints were not run...
229     assertFalse(CheckWasRunConstraint.wasRun);
230     table.close();
231   }
232 
233   @After
234   public void cleanup() throws Exception {
235     // cleanup
236     CheckWasRunConstraint.wasRun = false;
237     util.getHBaseAdmin().disableTable(tableName);
238     util.getHBaseAdmin().deleteTable(tableName);
239   }
240 
241   @AfterClass
242   public static void tearDownAfterClass() throws Exception {
243     util.shutdownMiniCluster();
244   }
245 
246   /**
247    * Constraint to check that it was actually run (or not)
248    */
249   public static class CheckWasRunConstraint extends BaseConstraint {
250     public static boolean wasRun = false;
251 
252     @Override
253     public void check(Put p) {
254       wasRun = true;
255     }
256   }
257 
258 }