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.assertEquals;
021import static org.junit.Assert.assertFalse;
022import static org.junit.Assert.assertTrue;
023import static org.junit.Assert.fail;
024
025import java.util.List;
026import org.apache.hadoop.conf.Configuration;
027import org.apache.hadoop.hbase.HBaseClassTestRule;
028import org.apache.hadoop.hbase.HTableDescriptor;
029import org.apache.hadoop.hbase.TableName;
030import org.apache.hadoop.hbase.client.Put;
031import org.apache.hadoop.hbase.constraint.TestConstraint.CheckWasRunConstraint;
032import org.apache.hadoop.hbase.constraint.WorksConstraint.NameConstraint;
033import org.apache.hadoop.hbase.testclassification.MiscTests;
034import org.apache.hadoop.hbase.testclassification.SmallTests;
035import org.apache.hadoop.hbase.util.Pair;
036import org.junit.ClassRule;
037import org.junit.Rule;
038import org.junit.Test;
039import org.junit.experimental.categories.Category;
040import org.junit.rules.TestName;
041
042/**
043 * Test reading/writing the constraints into the {@link HTableDescriptor}
044 */
045@Category({MiscTests.class, SmallTests.class})
046public class TestConstraints {
047
048  @ClassRule
049  public static final HBaseClassTestRule CLASS_RULE =
050      HBaseClassTestRule.forClass(TestConstraints.class);
051
052  @Rule
053  public TestName name = new TestName();
054
055  @SuppressWarnings("unchecked")
056  @Test
057  public void testSimpleReadWrite() throws Throwable {
058    HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName()));
059    Constraints.add(desc, WorksConstraint.class);
060
061    List<? extends Constraint> constraints = Constraints.getConstraints(desc,
062        this.getClass().getClassLoader());
063    assertEquals(1, constraints.size());
064
065    assertEquals(WorksConstraint.class, constraints.get(0).getClass());
066
067    // Check that we can add more than 1 constraint and that ordering is
068    // preserved
069    Constraints.add(desc, AlsoWorks.class, NameConstraint.class);
070    constraints = Constraints.getConstraints(desc, this.getClass()
071        .getClassLoader());
072    assertEquals(3, constraints.size());
073
074    assertEquals(WorksConstraint.class, constraints.get(0).getClass());
075    assertEquals(AlsoWorks.class, constraints.get(1).getClass());
076    assertEquals(NameConstraint.class, constraints.get(2).getClass());
077
078  }
079
080  @SuppressWarnings("unchecked")
081  @Test
082  public void testReadWriteWithConf() throws Throwable {
083    HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName()));
084    Constraints.add(desc,
085      new Pair<>(CheckConfigurationConstraint.class,
086        CheckConfigurationConstraint.getConfiguration()));
087
088    List<? extends Constraint> c = Constraints.getConstraints(desc, this
089        .getClass().getClassLoader());
090    assertEquals(1, c.size());
091
092    assertEquals(CheckConfigurationConstraint.class, c.get(0).getClass());
093
094    // check to make sure that we overwrite configurations
095    Constraints.add(desc, new Pair<>(
096        CheckConfigurationConstraint.class, new Configuration(false)));
097
098    try {
099      Constraints.getConstraints(desc, this.getClass().getClassLoader());
100      fail("No exception thrown  - configuration not overwritten");
101    } catch (IllegalArgumentException e) {
102      // expect to have the exception, so don't do anything
103    }
104  }
105
106  /**
107   * Test that Constraints are properly enabled, disabled, and removed
108   *
109   * @throws Exception
110   */
111  @SuppressWarnings("unchecked")
112  @Test
113  public void testEnableDisableRemove() throws Exception {
114    HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName()));
115    // check general enabling/disabling of constraints
116    // first add a constraint
117    Constraints.add(desc, AllPassConstraint.class);
118    // make sure everything is enabled
119    assertTrue(Constraints.enabled(desc, AllPassConstraint.class));
120    assertTrue(desc.hasCoprocessor(ConstraintProcessor.class.getName()));
121
122    // check disabling
123    Constraints.disable(desc);
124    assertFalse(desc.hasCoprocessor(ConstraintProcessor.class.getName()));
125    // make sure the added constraints are still present
126    assertTrue(Constraints.enabled(desc, AllPassConstraint.class));
127
128    // check just removing the single constraint
129    Constraints.remove(desc, AllPassConstraint.class);
130    assertFalse(Constraints.has(desc, AllPassConstraint.class));
131
132    // Add back the single constraint
133    Constraints.add(desc, AllPassConstraint.class);
134
135    // and now check that when we remove constraints, all are gone
136    Constraints.remove(desc);
137    assertFalse(desc.hasCoprocessor(ConstraintProcessor.class.getName()));
138    assertFalse(Constraints.has(desc, AllPassConstraint.class));
139
140  }
141
142  /**
143   * Test that when we update a constraint the ordering is not modified.
144   *
145   * @throws Exception
146   */
147  @SuppressWarnings("unchecked")
148  @Test
149  public void testUpdateConstraint() throws Exception {
150    HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName()));
151    Constraints.add(desc, CheckConfigurationConstraint.class,
152        CheckWasRunConstraint.class);
153    Constraints.setConfiguration(desc, CheckConfigurationConstraint.class,
154        CheckConfigurationConstraint.getConfiguration());
155
156    List<? extends Constraint> constraints = Constraints.getConstraints(desc,
157        this.getClass().getClassLoader());
158
159    assertEquals(2, constraints.size());
160
161    // check to make sure the order didn't change
162    assertEquals(CheckConfigurationConstraint.class, constraints.get(0)
163        .getClass());
164    assertEquals(CheckWasRunConstraint.class, constraints.get(1).getClass());
165  }
166
167  /**
168   * Test that if a constraint hasn't been set that there are no problems with
169   * attempting to remove it.
170   *
171   * @throws Throwable
172   *           on failure.
173   */
174  @Test
175  public void testRemoveUnsetConstraint() throws Throwable {
176    HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName()));
177    Constraints.remove(desc);
178    Constraints.remove(desc, AlsoWorks.class);
179  }
180
181  @Test
182  public void testConfigurationPreserved() throws Throwable {
183    Configuration conf = new Configuration();
184    conf.setBoolean("_ENABLED", false);
185    conf.setLong("_PRIORITY", 10);
186    HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName()));
187    Constraints.add(desc, AlsoWorks.class, conf);
188    Constraints.add(desc, WorksConstraint.class);
189    assertFalse(Constraints.enabled(desc, AlsoWorks.class));
190    List<? extends Constraint> constraints = Constraints.getConstraints(desc,
191        this.getClass().getClassLoader());
192    for (Constraint c : constraints) {
193      Configuration storedConf = c.getConf();
194      if (c instanceof AlsoWorks)
195        assertEquals(10, storedConf.getLong("_PRIORITY", -1));
196      // its just a worksconstraint
197      else
198        assertEquals(2, storedConf.getLong("_PRIORITY", -1));
199
200    }
201
202  }
203
204  // ---------- Constraints just used for testing
205
206  /**
207   * Also just works
208   */
209  public static class AlsoWorks extends BaseConstraint {
210    @Override
211    public void check(Put p) {
212      // NOOP
213    }
214  }
215
216}