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.master.balancer;
019
020import static org.apache.hadoop.hbase.master.balancer.HeterogeneousCostRulesTestHelper.DEFAULT_RULES_FILE_NAME;
021import static org.apache.hadoop.hbase.master.balancer.HeterogeneousCostRulesTestHelper.cleanup;
022import static org.apache.hadoop.hbase.master.balancer.HeterogeneousCostRulesTestHelper.createRulesFile;
023import static org.junit.Assert.assertEquals;
024
025import java.io.IOException;
026import java.util.Arrays;
027import java.util.Collections;
028import org.apache.hadoop.hbase.HBaseClassTestRule;
029import org.apache.hadoop.hbase.HBaseCommonTestingUtil;
030import org.apache.hadoop.hbase.testclassification.MasterTests;
031import org.apache.hadoop.hbase.testclassification.MediumTests;
032import org.junit.Before;
033import org.junit.BeforeClass;
034import org.junit.ClassRule;
035import org.junit.Rule;
036import org.junit.Test;
037import org.junit.experimental.categories.Category;
038import org.junit.rules.TestName;
039
040@Category({ MasterTests.class, MediumTests.class })
041public class TestStochasticLoadBalancerHeterogeneousCostRules extends StochasticBalancerTestBase {
042
043  @ClassRule
044  public static final HBaseClassTestRule CLASS_RULE =
045    HBaseClassTestRule.forClass(TestStochasticLoadBalancerHeterogeneousCostRules.class);
046  @Rule
047  public TestName name = new TestName();
048
049  private HeterogeneousRegionCountCostFunction costFunction;
050  private static final HBaseCommonTestingUtil HTU = new HBaseCommonTestingUtil();
051
052  /**
053   * Make a file for rules that is inside a temporary test dir named for the method so it doesn't
054   * clash w/ other rule files.
055   */
056  private String rulesFilename;
057
058  @BeforeClass
059  public static void beforeClass() throws IOException {
060    // Ensure test dir is created
061    HTU.getDataTestDir().getFileSystem(HTU.getConfiguration()).mkdirs(HTU.getDataTestDir());
062  }
063
064  @Before
065  public void before() throws IOException {
066    // New rules file name per test.
067    this.rulesFilename =
068      HTU.getDataTestDir(this.name.getMethodName() + "." + DEFAULT_RULES_FILE_NAME).toString();
069    // Set the created rules filename into the configuration.
070    HTU.getConfiguration().set(
071      HeterogeneousRegionCountCostFunction.HBASE_MASTER_BALANCER_HETEROGENEOUS_RULES_FILE,
072      this.rulesFilename);
073  }
074
075  @Test
076  public void testNoRules() throws IOException {
077    // Override what is in the configuration with the name of a non-existent file!
078    HTU.getConfiguration().set(
079      HeterogeneousRegionCountCostFunction.HBASE_MASTER_BALANCER_HETEROGENEOUS_RULES_FILE,
080      "non-existent-file!");
081    this.costFunction = new HeterogeneousRegionCountCostFunction(HTU.getConfiguration());
082    this.costFunction.loadRules();
083    assertEquals(0, this.costFunction.getNumberOfRulesLoaded());
084  }
085
086  @Test
087  public void testBadFormatInRules() throws IOException {
088    // See {@link #before} above. It sets this.rulesFilename, and
089    // HeterogeneousRegionCountCostFunction.HBASE_MASTER_BALANCER_HETEROGENEOUS_RULES_FILE,
090    // in the configuration.
091    this.costFunction = new HeterogeneousRegionCountCostFunction(HTU.getConfiguration());
092    this.costFunction.loadRules();
093    assertEquals(0, this.costFunction.getNumberOfRulesLoaded());
094
095    createRulesFile(this.rulesFilename, Collections.singletonList("bad rules format"));
096    this.costFunction = new HeterogeneousRegionCountCostFunction(HTU.getConfiguration());
097    this.costFunction.loadRules();
098    assertEquals(0, this.costFunction.getNumberOfRulesLoaded());
099
100    createRulesFile(this.rulesFilename, Arrays.asList("srv[1-2] 10", "bad_rules format", "a"));
101    this.costFunction = new HeterogeneousRegionCountCostFunction(HTU.getConfiguration());
102    this.costFunction.loadRules();
103    assertEquals(1, this.costFunction.getNumberOfRulesLoaded());
104  }
105
106  @Test
107  public void testTwoRules() throws IOException {
108    // See {@link #before} above. It sets this.rulesFilename, and
109    // HeterogeneousRegionCountCostFunction.HBASE_MASTER_BALANCER_HETEROGENEOUS_RULES_FILE,
110    // in the configuration.
111    // See {@link #before} above. It sets
112    // HeterogeneousRegionCountCostFunction.HBASE_MASTER_BALANCER_HETEROGENEOUS_RULES_FILE,
113    // in the configuration.
114    createRulesFile(this.rulesFilename, Arrays.asList("^server1$ 10", "^server2 21"));
115    this.costFunction = new HeterogeneousRegionCountCostFunction(HTU.getConfiguration());
116    this.costFunction.loadRules();
117    assertEquals(2, this.costFunction.getNumberOfRulesLoaded());
118  }
119
120  @Test
121  public void testBadRegexp() throws IOException {
122    // See {@link #before} above. It sets this.rulesFilename, and
123    // HeterogeneousRegionCountCostFunction.HBASE_MASTER_BALANCER_HETEROGENEOUS_RULES_FILE,
124    // in the configuration.
125    // See {@link #before} above. It sets
126    // HeterogeneousRegionCountCostFunction.HBASE_MASTER_BALANCER_HETEROGENEOUS_RULES_FILE,
127    // in the configuration.
128    createRulesFile(this.rulesFilename, Collections.singletonList("server[ 1"));
129    this.costFunction = new HeterogeneousRegionCountCostFunction(HTU.getConfiguration());
130    this.costFunction.loadRules();
131    assertEquals(0, this.costFunction.getNumberOfRulesLoaded());
132  }
133
134  @Test
135  public void testNoOverride() throws IOException {
136    // See {@link #before} above. It sets this.rulesFilename, and
137    // HeterogeneousRegionCountCostFunction.HBASE_MASTER_BALANCER_HETEROGENEOUS_RULES_FILE,
138    // in the configuration.
139    createRulesFile(this.rulesFilename, Arrays.asList("^server1$ 10", "^server2 21"));
140    this.costFunction = new HeterogeneousRegionCountCostFunction(HTU.getConfiguration());
141    this.costFunction.loadRules();
142    assertEquals(2, this.costFunction.getNumberOfRulesLoaded());
143
144    // loading malformed configuration does not overload current
145    cleanup(this.rulesFilename);
146    this.costFunction.loadRules();
147    assertEquals(2, this.costFunction.getNumberOfRulesLoaded());
148  }
149}