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.http;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertNotNull;
022import static org.junit.Assert.assertNull;
023
024import java.io.IOException;
025import java.util.ArrayList;
026import java.util.Collections;
027import java.util.HashMap;
028import java.util.List;
029import java.util.Map;
030import java.util.Optional;
031import org.apache.hadoop.conf.Configuration;
032import org.apache.hadoop.hbase.HBaseClassTestRule;
033import org.apache.hadoop.hbase.HBaseConfiguration;
034import org.apache.hadoop.hbase.ServerName;
035import org.apache.hadoop.hbase.TableDescriptors;
036import org.apache.hadoop.hbase.TableName;
037import org.apache.hadoop.hbase.client.RegionInfo;
038import org.apache.hadoop.hbase.client.RegionInfoBuilder;
039import org.apache.hadoop.hbase.client.TableDescriptor;
040import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
041import org.apache.hadoop.hbase.master.DeadServer;
042import org.apache.hadoop.hbase.master.HMaster;
043import org.apache.hadoop.hbase.master.RegionState;
044import org.apache.hadoop.hbase.master.ServerManager;
045import org.apache.hadoop.hbase.master.assignment.AssignmentManager;
046import org.apache.hadoop.hbase.master.assignment.RegionStateNode;
047import org.apache.hadoop.hbase.master.assignment.RegionStates;
048import org.apache.hadoop.hbase.testclassification.MasterTests;
049import org.apache.hadoop.hbase.testclassification.SmallTests;
050import org.apache.hadoop.hbase.util.Bytes;
051import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
052import org.apache.hadoop.hbase.zookeeper.ZNodePaths;
053import org.junit.Before;
054import org.junit.ClassRule;
055import org.junit.Test;
056import org.junit.experimental.categories.Category;
057import org.mockito.Mockito;
058
059@Category({ MasterTests.class, SmallTests.class })
060public class TestMasterStatusUtil {
061
062  @ClassRule
063  public static final HBaseClassTestRule CLASS_RULE =
064    HBaseClassTestRule.forClass(TestMasterStatusUtil.class);
065
066  private HMaster master;
067  private Configuration conf;
068
069  static final ServerName FAKE_HOST = ServerName.valueOf("fakehost", 12345, 1234567890);
070  static final TableDescriptor FAKE_TABLE =
071    TableDescriptorBuilder.newBuilder(TableName.valueOf("mytable")).build();
072
073  static final RegionInfo FAKE_HRI = RegionInfoBuilder.newBuilder(FAKE_TABLE.getTableName())
074    .setStartKey(Bytes.toBytes("a")).setEndKey(Bytes.toBytes("b")).build();
075
076  @Before
077  public void setupBasicMocks() {
078    conf = HBaseConfiguration.create();
079
080    master = Mockito.mock(HMaster.class);
081    Mockito.doReturn(FAKE_HOST).when(master).getServerName();
082    Mockito.doReturn(conf).when(master).getConfiguration();
083    Mockito.doReturn(true).when(master).isInitialized();
084
085    // Fake DeadServer
086    DeadServer deadServer = Mockito.mock(DeadServer.class);
087    // Fake serverManager
088    ServerManager serverManager = Mockito.mock(ServerManager.class);
089    Mockito.doReturn(1.0).when(serverManager).getAverageLoad();
090    Mockito.doReturn(serverManager).when(master).getServerManager();
091    Mockito.doReturn(deadServer).when(serverManager).getDeadServers();
092
093    // Fake AssignmentManager and RIT
094    AssignmentManager am = Mockito.mock(AssignmentManager.class);
095    RegionStates rs = Mockito.mock(RegionStates.class);
096    List<RegionState> regionsInTransition = new ArrayList<>();
097    regionsInTransition
098      .add(new RegionState(FAKE_HRI, RegionState.State.CLOSING, 12345L, FAKE_HOST));
099    Mockito.doReturn(rs).when(am).getRegionStates();
100    Mockito.doReturn(regionsInTransition).when(rs).getRegionsInTransition();
101    Mockito.doReturn(am).when(master).getAssignmentManager();
102    Mockito.doReturn(serverManager).when(master).getServerManager();
103
104    // Fake ZKW
105    ZKWatcher zkw = Mockito.mock(ZKWatcher.class);
106    Mockito.doReturn(new ZNodePaths(conf)).when(zkw).getZNodePaths();
107    Mockito.doReturn("fakequorum").when(zkw).getQuorum();
108    Mockito.doReturn(zkw).when(master).getZooKeeper();
109
110    // Fake ActiveMaster
111    Mockito.doReturn(Optional.of(FAKE_HOST)).when(master).getActiveMaster();
112  }
113
114  @Test
115  public void testGetUserTables() throws IOException {
116    Map<String, TableDescriptor> mockTables = new HashMap<>();
117    mockTables.put("foo", TableDescriptorBuilder.newBuilder(TableName.valueOf("foo")).build());
118    mockTables.put("bar", TableDescriptorBuilder.newBuilder(TableName.valueOf("bar")).build());
119
120    TableDescriptors tableDescriptors = Mockito.mock(TableDescriptors.class);
121    Mockito.doReturn(tableDescriptors).when(master).getTableDescriptors();
122
123    Mockito.doReturn(mockTables).when(tableDescriptors).getAll();
124
125    List<TableDescriptor> tables = new ArrayList<>();
126
127    String errorMessage = MasterStatusUtil.getUserTables(master, tables);
128
129    assertNull(errorMessage);
130    assertEquals(2, tables.size());
131  }
132
133  @Test
134  public void testGetUserTablesFilterOutSystemTables() throws IOException {
135    Map<String, TableDescriptor> mockTables = new HashMap<>();
136    mockTables.put("foo", TableDescriptorBuilder.newBuilder(TableName.valueOf("foo")).build());
137    mockTables.put("bar", TableDescriptorBuilder.newBuilder(TableName.valueOf("bar")).build());
138    mockTables.put("meta",
139      TableDescriptorBuilder.newBuilder(TableName.valueOf("hbase", "meta")).build());
140
141    TableDescriptors tableDescriptors = Mockito.mock(TableDescriptors.class);
142    Mockito.doReturn(tableDescriptors).when(master).getTableDescriptors();
143
144    Mockito.doReturn(mockTables).when(tableDescriptors).getAll();
145
146    List<TableDescriptor> tables = new ArrayList<>();
147
148    String errorMessage = MasterStatusUtil.getUserTables(master, tables);
149
150    assertNull(errorMessage);
151    assertEquals(2, tables.size());
152  }
153
154  @Test
155  public void testGetUserTablesNoUserTables() throws IOException {
156    Map<Object, Object> emptyMap = Collections.emptyMap();
157
158    TableDescriptors tableDescriptors = Mockito.mock(TableDescriptors.class);
159    Mockito.doReturn(tableDescriptors).when(master).getTableDescriptors();
160
161    Mockito.doReturn(emptyMap).when(tableDescriptors).getAll();
162
163    List<TableDescriptor> tables = new ArrayList<>();
164
165    String errorMessage = MasterStatusUtil.getUserTables(master, tables);
166
167    assertNull(errorMessage);
168    assertEquals(0, tables.size());
169  }
170
171  @Test
172  public void testGetUserTablesMasterNotInitialized() {
173    Mockito.doReturn(false).when(master).isInitialized();
174
175    List<TableDescriptor> tables = new ArrayList<>();
176
177    String errorMessage = MasterStatusUtil.getUserTables(master, tables);
178
179    assertNull(errorMessage);
180    assertEquals(0, tables.size());
181  }
182
183  @Test
184  public void testGetUserTablesException() throws IOException {
185    TableDescriptors tableDescriptors = Mockito.mock(TableDescriptors.class);
186    Mockito.doReturn(tableDescriptors).when(master).getTableDescriptors();
187
188    Mockito.doThrow(new IOException("some error")).when(tableDescriptors).getAll();
189
190    List<TableDescriptor> tables = new ArrayList<>();
191    String errorMessage = MasterStatusUtil.getUserTables(master, tables);
192    assertEquals("Got user tables error, some error", errorMessage);
193  }
194
195  @Test
196  public void testGetFragmentationInfoTurnedOff() throws IOException {
197    conf.setBoolean("hbase.master.ui.fragmentation.enabled", false);
198    assertNull(MasterStatusUtil.getFragmentationInfo(master, conf));
199  }
200
201  @Test
202  public void testGetFragmentationInfoTurnedOn() throws IOException {
203    conf.setBoolean("hbase.master.ui.fragmentation.enabled", true);
204    Map<String, Integer> fragmentationInfo = MasterStatusUtil.getFragmentationInfo(master, conf);
205    assertNotNull(fragmentationInfo);
206    assertEquals(1, fragmentationInfo.size());
207  }
208
209  @Test
210  public void testGetMetaLocationOrNull() {
211    mockMetaLocation(true);
212
213    ServerName location = MasterStatusUtil.getMetaLocationOrNull(master);
214    assertNotNull(location);
215    assertEquals(FAKE_HOST, location);
216  }
217
218  @Test
219  public void testGetMetaLocationOrNullNotOpen() {
220    mockMetaLocation(false);
221
222    ServerName location = MasterStatusUtil.getMetaLocationOrNull(master);
223    assertNull(location);
224  }
225
226  private void mockMetaLocation(boolean isOpen) {
227    RegionStates rs = master.getAssignmentManager().getRegionStates();
228    RegionStateNode rsn = Mockito.mock(RegionStateNode.class);
229    Mockito.doReturn(rsn).when(rs).getRegionStateNode(RegionInfoBuilder.FIRST_META_REGIONINFO);
230    Mockito.doReturn(isOpen).when(rsn).isInState(RegionState.State.OPEN);
231    if (isOpen) {
232      Mockito.doReturn(FAKE_HOST).when(rsn).getRegionLocation();
233    }
234  }
235
236  @Test
237  public void testServerNameLink() {
238    Mockito.doReturn(16030).when(master).getRegionServerInfoPort(FAKE_HOST);
239
240    String link = MasterStatusUtil.serverNameLink(master, FAKE_HOST);
241
242    assertNotNull(link);
243    assertEquals("<a href=\"//fakehost:16030/rs-status\">fakehost,12345,1234567890</a>", link);
244  }
245
246  @Test
247  public void testServerNameLinkNoInfoPort() {
248    Mockito.doReturn(-1).when(master).getRegionServerInfoPort(FAKE_HOST);
249
250    String link = MasterStatusUtil.serverNameLink(master, FAKE_HOST);
251
252    assertNotNull(link);
253    assertEquals("fakehost,12345,1234567890", link);
254  }
255}