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