View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.master;
20  
21  import static org.junit.Assert.*;
22  
23  import java.io.IOException;
24  import java.io.StringWriter;
25  import java.util.HashSet;
26  import java.util.List;
27  import java.util.NavigableMap;
28  import java.util.Set;
29  import java.util.regex.Matcher;
30  import java.util.regex.Pattern;
31  
32  import org.apache.hadoop.conf.Configuration;
33  import org.apache.hadoop.hbase.*;
34  import org.apache.hadoop.hbase.client.HBaseAdmin;
35  import org.apache.hadoop.hbase.util.Bytes;
36  import org.apache.hadoop.hbase.zookeeper.MasterAddressTracker;
37  import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
38  import org.apache.hadoop.hbase.tmpl.master.AssignmentManagerStatusTmpl;
39  import org.apache.hadoop.hbase.tmpl.master.MasterStatusTmpl;
40  import org.junit.Before;
41  import org.junit.Test;
42  import org.junit.experimental.categories.Category;
43  import org.mockito.Mockito;
44  
45  import com.google.common.collect.Lists;
46  import com.google.common.collect.Maps;
47  
48  /**
49   * Tests for the master status page and its template.
50   */
51  @Category(MediumTests.class)
52  public class TestMasterStatusServlet {
53    
54    private HMaster master;
55    private Configuration conf;
56    private HBaseAdmin admin;
57  
58    static final ServerName FAKE_HOST =
59        ServerName.valueOf("fakehost", 12345, 1234567890);
60    static final HTableDescriptor FAKE_TABLE =
61      new HTableDescriptor(TableName.valueOf("mytable"));
62    static final HRegionInfo FAKE_HRI =
63        new HRegionInfo(FAKE_TABLE.getTableName(),
64            Bytes.toBytes("a"), Bytes.toBytes("b"));
65  
66    @Before
67    public void setupBasicMocks() {
68      conf = HBaseConfiguration.create();
69  
70      master = Mockito.mock(HMaster.class);
71      Mockito.doReturn(FAKE_HOST).when(master).getServerName();
72      Mockito.doReturn(conf).when(master).getConfiguration();
73  
74      //Fake DeadServer
75      DeadServer deadServer = Mockito.mock(DeadServer.class);
76      // Fake serverManager
77      ServerManager serverManager = Mockito.mock(ServerManager.class);
78      Mockito.doReturn(1.0).when(serverManager).getAverageLoad();
79      Mockito.doReturn(serverManager).when(master).getServerManager();
80      Mockito.doReturn(deadServer).when(serverManager).getDeadServers();
81  
82      // Fake AssignmentManager and RIT
83      AssignmentManager am = Mockito.mock(AssignmentManager.class);
84      RegionStates rs = Mockito.mock(RegionStates.class);
85      NavigableMap<String, RegionState> regionsInTransition =
86        Maps.newTreeMap();
87      regionsInTransition.put("r1",
88        new RegionState(FAKE_HRI, RegionState.State.CLOSING, 12345L, FAKE_HOST));
89      Mockito.doReturn(rs).when(am).getRegionStates();
90      Mockito.doReturn(regionsInTransition).when(rs).getRegionsInTransition();
91      Mockito.doReturn(am).when(master).getAssignmentManager();
92      Mockito.doReturn(serverManager).when(master).getServerManager();
93  
94      // Fake ZKW
95      ZooKeeperWatcher zkw = Mockito.mock(ZooKeeperWatcher.class);
96      Mockito.doReturn("fakequorum").when(zkw).getQuorum();
97      Mockito.doReturn(zkw).when(master).getZooKeeperWatcher();
98  
99      // Fake MasterAddressTracker
100     MasterAddressTracker tracker = Mockito.mock(MasterAddressTracker.class);
101     Mockito.doReturn(tracker).when(master).getMasterAddressTracker();
102     Mockito.doReturn(FAKE_HOST).when(tracker).getMasterAddress();
103 
104     // Mock admin
105     admin = Mockito.mock(HBaseAdmin.class); 
106   }
107 
108   private void setupMockTables() throws IOException {
109     HTableDescriptor tables[] = new HTableDescriptor[] {
110         new HTableDescriptor(TableName.valueOf("foo")),
111         new HTableDescriptor(TableName.valueOf("bar"))
112     };
113     Mockito.doReturn(tables).when(admin).listTables();
114   }
115   
116   @Test
117   public void testStatusTemplateNoTables() throws IOException {
118     new MasterStatusTmpl().render(new StringWriter(),
119         master, admin);
120   }
121 
122   @Test
123   public void testStatusTemplateMetaAvailable() throws IOException {
124     setupMockTables();
125     
126     new MasterStatusTmpl()
127       .setMetaLocation(ServerName.valueOf("metaserver:123,12345"))
128       .render(new StringWriter(),
129         master, admin);
130   }
131 
132   @Test
133   public void testStatusTemplateWithServers() throws IOException {
134     setupMockTables();
135     
136     List<ServerName> servers = Lists.newArrayList(
137         ServerName.valueOf("rootserver:123,12345"),
138         ServerName.valueOf("metaserver:123,12345"));
139     Set<ServerName> deadServers = new HashSet<ServerName>(
140         Lists.newArrayList(
141             ServerName.valueOf("badserver:123,12345"),
142             ServerName.valueOf("uglyserver:123,12345"))
143     );
144 
145     new MasterStatusTmpl()
146       .setMetaLocation(ServerName.valueOf("metaserver:123,12345"))
147       .setServers(servers)
148       .setDeadServers(deadServers)
149       .render(new StringWriter(),
150         master, admin);
151   }
152   
153   @Test
154   public void testAssignmentManagerTruncatedList() throws IOException {
155     AssignmentManager am = Mockito.mock(AssignmentManager.class);
156     RegionStates rs = Mockito.mock(RegionStates.class);
157 
158     // Add 100 regions as in-transition
159     NavigableMap<String, RegionState> regionsInTransition =
160       Maps.newTreeMap();
161     for (byte i = 0; i < 100; i++) {
162       HRegionInfo hri = new HRegionInfo(FAKE_TABLE.getTableName(),
163           new byte[]{i}, new byte[]{(byte) (i+1)});
164       regionsInTransition.put(hri.getEncodedName(),
165         new RegionState(hri, RegionState.State.CLOSING, 12345L, FAKE_HOST));
166     }
167     // Add hbase:meta in transition as well
168     regionsInTransition.put(
169         HRegionInfo.FIRST_META_REGIONINFO.getEncodedName(),
170         new RegionState(HRegionInfo.FIRST_META_REGIONINFO,
171                         RegionState.State.CLOSING, 12345L, FAKE_HOST));
172     Mockito.doReturn(rs).when(am).getRegionStates();
173     Mockito.doReturn(regionsInTransition).when(rs).getRegionsInTransition();
174 
175     // Render to a string
176     StringWriter sw = new StringWriter();
177     new AssignmentManagerStatusTmpl()
178       .setLimit(50)
179       .render(sw, am);
180     String result = sw.toString();
181 
182     // Should always include META
183     assertTrue(result.contains(HRegionInfo.FIRST_META_REGIONINFO.getEncodedName()));
184     
185     // Make sure we only see 50 of them
186     Matcher matcher = Pattern.compile("CLOSING").matcher(result);
187     int count = 0;
188     while (matcher.find()) {
189       count++;
190     }
191     assertEquals(50, count);
192   }
193 
194 }
195