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