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