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; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertFalse; 022import static org.junit.Assert.assertNotEquals; 023import static org.junit.Assert.assertTrue; 024import static org.mockito.ArgumentMatchers.anyInt; 025import static org.mockito.Mockito.mock; 026import static org.mockito.Mockito.when; 027 028import java.io.File; 029import java.io.IOException; 030import java.util.HashMap; 031import java.util.List; 032import java.util.Map; 033import java.util.Map.Entry; 034import java.util.Random; 035import org.apache.hadoop.conf.Configuration; 036import org.apache.hadoop.fs.FileSystem; 037import org.apache.hadoop.fs.FileUtil; 038import org.apache.hadoop.fs.Path; 039import org.apache.hadoop.hbase.client.Get; 040import org.apache.hadoop.hbase.client.Put; 041import org.apache.hadoop.hbase.client.Result; 042import org.apache.hadoop.hbase.client.Table; 043import org.apache.hadoop.hbase.http.ssl.KeyStoreTestUtil; 044import org.apache.hadoop.hbase.testclassification.LargeTests; 045import org.apache.hadoop.hbase.testclassification.MiscTests; 046import org.apache.hadoop.hbase.util.Bytes; 047import org.apache.hadoop.hbase.zookeeper.MiniZooKeeperCluster; 048import org.apache.hadoop.hdfs.MiniDFSCluster; 049import org.junit.ClassRule; 050import org.junit.Rule; 051import org.junit.Test; 052import org.junit.experimental.categories.Category; 053import org.junit.rules.TestName; 054import org.mockito.Mockito; 055import org.mockito.invocation.InvocationOnMock; 056import org.mockito.stubbing.Answer; 057import org.slf4j.Logger; 058import org.slf4j.LoggerFactory; 059 060/** 061 * Test our testing utility class 062 */ 063@Category({MiscTests.class, LargeTests.class}) 064public class TestHBaseTestingUtility { 065 066 @ClassRule 067 public static final HBaseClassTestRule CLASS_RULE = 068 HBaseClassTestRule.forClass(TestHBaseTestingUtility.class); 069 070 private static final Logger LOG = LoggerFactory.getLogger(TestHBaseTestingUtility.class); 071 072 @Rule 073 public TestName name = new TestName(); 074 075 /** 076 * Basic sanity test that spins up multiple HDFS and HBase clusters that share 077 * the same ZK ensemble. We then create the same table in both and make sure 078 * that what we insert in one place doesn't end up in the other. 079 * @throws Exception 080 */ 081 @Test 082 public void testMultiClusters() throws Exception { 083 // Create three clusters 084 085 // Cluster 1. 086 HBaseTestingUtility htu1 = new HBaseTestingUtility(); 087 // Set a different zk path for each cluster 088 htu1.getConfiguration().set(HConstants.ZOOKEEPER_ZNODE_PARENT, "/1"); 089 htu1.startMiniZKCluster(); 090 091 // Cluster 2 092 HBaseTestingUtility htu2 = new HBaseTestingUtility(); 093 htu2.getConfiguration().set(HConstants.ZOOKEEPER_ZNODE_PARENT, "/2"); 094 htu2.getConfiguration().set(HConstants.ZOOKEEPER_CLIENT_PORT, 095 htu1.getConfiguration().get(HConstants.ZOOKEEPER_CLIENT_PORT, "-1")); 096 htu2.setZkCluster(htu1.getZkCluster()); 097 098 // Cluster 3; seed it with the conf from htu1 so we pickup the 'right' 099 // zk cluster config; it is set back into the config. as part of the 100 // start of minizkcluster. 101 HBaseTestingUtility htu3 = new HBaseTestingUtility(); 102 htu3.getConfiguration().set(HConstants.ZOOKEEPER_ZNODE_PARENT, "/3"); 103 htu3.getConfiguration().set(HConstants.ZOOKEEPER_CLIENT_PORT, 104 htu1.getConfiguration().get(HConstants.ZOOKEEPER_CLIENT_PORT, "-1")); 105 htu3.setZkCluster(htu1.getZkCluster()); 106 107 try { 108 htu1.startMiniCluster(); 109 htu2.startMiniCluster(); 110 htu3.startMiniCluster(); 111 112 final TableName tableName = TableName.valueOf(name.getMethodName()); 113 final byte[] FAM_NAME = Bytes.toBytes("fam"); 114 final byte[] ROW = Bytes.toBytes("row"); 115 final byte[] QUAL_NAME = Bytes.toBytes("qual"); 116 final byte[] VALUE = Bytes.toBytes("value"); 117 118 Table table1 = htu1.createTable(tableName, FAM_NAME); 119 Table table2 = htu2.createTable(tableName, FAM_NAME); 120 121 Put put = new Put(ROW); 122 put.addColumn(FAM_NAME, QUAL_NAME, VALUE); 123 table1.put(put); 124 125 Get get = new Get(ROW); 126 get.addColumn(FAM_NAME, QUAL_NAME); 127 Result res = table1.get(get); 128 assertEquals(1, res.size()); 129 130 res = table2.get(get); 131 assertEquals(0, res.size()); 132 133 table1.close(); 134 table2.close(); 135 136 } finally { 137 htu3.shutdownMiniCluster(); 138 htu2.shutdownMiniCluster(); 139 htu1.shutdownMiniCluster(); 140 } 141 } 142 143 @Test public void testMiniCluster() throws Exception { 144 HBaseTestingUtility hbt = new HBaseTestingUtility(); 145 146 MiniHBaseCluster cluster = hbt.startMiniCluster(); 147 try { 148 assertEquals(1, cluster.getLiveRegionServerThreads().size()); 149 } finally { 150 hbt.shutdownMiniCluster(); 151 } 152 } 153 154 @Test 155 public void testMiniClusterBindToWildcard() throws Exception { 156 HBaseTestingUtility hbt = new HBaseTestingUtility(); 157 hbt.getConfiguration().set("hbase.regionserver.ipc.address", "0.0.0.0"); 158 MiniHBaseCluster cluster = hbt.startMiniCluster(); 159 try { 160 assertEquals(1, cluster.getLiveRegionServerThreads().size()); 161 } finally { 162 hbt.shutdownMiniCluster(); 163 } 164 } 165 166 @Test 167 public void testMiniClusterWithSSLOn() throws Exception { 168 final String BASEDIR = System.getProperty("test.build.dir", 169 "target/test-dir") + "/" + TestHBaseTestingUtility.class.getSimpleName(); 170 String sslConfDir = KeyStoreTestUtil.getClasspathDir(TestHBaseTestingUtility.class); 171 String keystoresDir = new File(BASEDIR).getAbsolutePath(); 172 173 HBaseTestingUtility hbt = new HBaseTestingUtility(); 174 File base = new File(BASEDIR); 175 FileUtil.fullyDelete(base); 176 base.mkdirs(); 177 178 KeyStoreTestUtil.setupSSLConfig(keystoresDir, sslConfDir, hbt.getConfiguration(), false); 179 180 hbt.getConfiguration().set("hbase.ssl.enabled", "true"); 181 hbt.getConfiguration().addResource("ssl-server.xml"); 182 hbt.getConfiguration().addResource("ssl-client.xml"); 183 184 MiniHBaseCluster cluster = hbt.startMiniCluster(); 185 try { 186 assertEquals(1, cluster.getLiveRegionServerThreads().size()); 187 } finally { 188 hbt.shutdownMiniCluster(); 189 } 190 } 191 192 /** 193 * Test that we can start and stop multiple time a cluster 194 * with the same HBaseTestingUtility. 195 */ 196 @Test public void testMultipleStartStop() throws Exception{ 197 HBaseTestingUtility htu1 = new HBaseTestingUtility(); 198 Path foo = new Path("foo"); 199 200 htu1.startMiniCluster(); 201 htu1.getDFSCluster().getFileSystem().create(foo); 202 assertTrue( htu1.getDFSCluster().getFileSystem().exists(foo)); 203 htu1.shutdownMiniCluster(); 204 205 htu1.startMiniCluster(); 206 assertFalse( htu1.getDFSCluster().getFileSystem().exists(foo)); 207 htu1.getDFSCluster().getFileSystem().create(foo); 208 assertTrue( htu1.getDFSCluster().getFileSystem().exists(foo)); 209 htu1.shutdownMiniCluster(); 210 } 211 212 @Test 213 public void testMiniZooKeeperWithOneServer() throws Exception { 214 HBaseTestingUtility hbt = new HBaseTestingUtility(); 215 MiniZooKeeperCluster cluster1 = hbt.startMiniZKCluster(); 216 try { 217 assertEquals(0, cluster1.getBackupZooKeeperServerNum()); 218 assertTrue((cluster1.killCurrentActiveZooKeeperServer() == -1)); 219 } finally { 220 hbt.shutdownMiniZKCluster(); 221 } 222 } 223 224 @Test 225 public void testMiniZooKeeperWithMultipleServers() throws Exception { 226 HBaseTestingUtility hbt = new HBaseTestingUtility(); 227 // set up zookeeper cluster with 5 zk servers 228 MiniZooKeeperCluster cluster2 = hbt.startMiniZKCluster(5); 229 int defaultClientPort = 21818; 230 cluster2.setDefaultClientPort(defaultClientPort); 231 try { 232 assertEquals(4, cluster2.getBackupZooKeeperServerNum()); 233 234 // killing the current active zk server 235 int currentActivePort = cluster2.killCurrentActiveZooKeeperServer(); 236 assertTrue(currentActivePort >= defaultClientPort); 237 // Check if the client port is returning a proper value 238 assertTrue(cluster2.getClientPort() == currentActivePort); 239 240 // kill another active zk server 241 currentActivePort = cluster2.killCurrentActiveZooKeeperServer(); 242 assertTrue(currentActivePort >= defaultClientPort); 243 assertTrue(cluster2.getClientPort() == currentActivePort); 244 assertEquals(2, cluster2.getBackupZooKeeperServerNum()); 245 assertEquals(3, cluster2.getZooKeeperServerNum()); 246 247 // killing the backup zk servers 248 cluster2.killOneBackupZooKeeperServer(); 249 cluster2.killOneBackupZooKeeperServer(); 250 assertEquals(0, cluster2.getBackupZooKeeperServerNum()); 251 assertEquals(1, cluster2.getZooKeeperServerNum()); 252 253 // killing the last zk server 254 currentActivePort = cluster2.killCurrentActiveZooKeeperServer(); 255 assertTrue(currentActivePort == -1); 256 assertTrue(cluster2.getClientPort() == currentActivePort); 257 // this should do nothing. 258 cluster2.killOneBackupZooKeeperServer(); 259 assertEquals(-1, cluster2.getBackupZooKeeperServerNum()); 260 assertEquals(0, cluster2.getZooKeeperServerNum()); 261 } finally { 262 hbt.shutdownMiniZKCluster(); 263 } 264 } 265 266 @Test 267 public void testMiniZooKeeperWithMultipleClientPorts() throws Exception { 268 int defaultClientPort = 8888; 269 int i, j; 270 HBaseTestingUtility hbt = new HBaseTestingUtility(); 271 272 // Test 1 - set up zookeeper cluster with same number of ZK servers and specified client ports 273 int [] clientPortList1 = {1111, 1112, 1113}; 274 MiniZooKeeperCluster cluster1 = hbt.startMiniZKCluster(clientPortList1.length, clientPortList1); 275 try { 276 List<Integer> clientPortListInCluster = cluster1.getClientPortList(); 277 278 for (i = 0; i < clientPortListInCluster.size(); i++) { 279 assertEquals(clientPortListInCluster.get(i).intValue(), clientPortList1[i]); 280 } 281 } finally { 282 hbt.shutdownMiniZKCluster(); 283 } 284 285 // Test 2 - set up zookeeper cluster with more ZK servers than specified client ports 286 hbt.getConfiguration().setInt("test.hbase.zookeeper.property.clientPort", defaultClientPort); 287 int [] clientPortList2 = {2222, 2223}; 288 MiniZooKeeperCluster cluster2 = 289 hbt.startMiniZKCluster(clientPortList2.length + 2, clientPortList2); 290 291 try { 292 List<Integer> clientPortListInCluster = cluster2.getClientPortList(); 293 294 for (i = 0, j = 0; i < clientPortListInCluster.size(); i++) { 295 if (i < clientPortList2.length) { 296 assertEquals(clientPortListInCluster.get(i).intValue(), clientPortList2[i]); 297 } else { 298 // servers with no specified client port will use defaultClientPort or some other ports 299 // based on defaultClientPort 300 assertEquals(clientPortListInCluster.get(i).intValue(), defaultClientPort + j); 301 j++; 302 } 303 } 304 } finally { 305 hbt.shutdownMiniZKCluster(); 306 } 307 308 // Test 3 - set up zookeeper cluster with invalid client ports 309 hbt.getConfiguration().setInt("test.hbase.zookeeper.property.clientPort", defaultClientPort); 310 int [] clientPortList3 = {3333, -3334, 3335, 0}; 311 MiniZooKeeperCluster cluster3 = 312 hbt.startMiniZKCluster(clientPortList3.length + 1, clientPortList3); 313 314 try { 315 List<Integer> clientPortListInCluster = cluster3.getClientPortList(); 316 317 for (i = 0, j = 0; i < clientPortListInCluster.size(); i++) { 318 // Servers will only use valid client ports; if ports are not specified or invalid, 319 // the default port or a port based on default port will be used. 320 if (i < clientPortList3.length && clientPortList3[i] > 0) { 321 assertEquals(clientPortListInCluster.get(i).intValue(), clientPortList3[i]); 322 } else { 323 assertEquals(clientPortListInCluster.get(i).intValue(), defaultClientPort + j); 324 j++; 325 } 326 } 327 } finally { 328 hbt.shutdownMiniZKCluster(); 329 } 330 331 // Test 4 - set up zookeeper cluster with default port and some other ports used 332 // This test tests that the defaultClientPort and defaultClientPort+2 are used, so 333 // the algorithm should choice defaultClientPort+1 and defaultClientPort+3 to fill 334 // out the ports for servers without ports specified. 335 hbt.getConfiguration().setInt("test.hbase.zookeeper.property.clientPort", defaultClientPort); 336 int [] clientPortList4 = {-4444, defaultClientPort+2, 4446, defaultClientPort}; 337 MiniZooKeeperCluster cluster4 = 338 hbt.startMiniZKCluster(clientPortList4.length + 1, clientPortList4); 339 340 try { 341 List<Integer> clientPortListInCluster = cluster4.getClientPortList(); 342 343 for (i = 0, j = 1; i < clientPortListInCluster.size(); i++) { 344 // Servers will only use valid client ports; if ports are not specified or invalid, 345 // the default port or a port based on default port will be used. 346 if (i < clientPortList4.length && clientPortList4[i] > 0) { 347 assertEquals(clientPortListInCluster.get(i).intValue(), clientPortList4[i]); 348 } else { 349 assertEquals(clientPortListInCluster.get(i).intValue(), defaultClientPort + j); 350 j +=2; 351 } 352 } 353 } finally { 354 hbt.shutdownMiniZKCluster(); 355 } 356 357 // Test 5 - set up zookeeper cluster with same ports specified - fail is expected. 358 int [] clientPortList5 = {5555, 5556, 5556}; 359 360 try { 361 MiniZooKeeperCluster cluster5 = 362 hbt.startMiniZKCluster(clientPortList5.length, clientPortList5); 363 assertTrue(cluster5.getClientPort() == -1); // expected failure 364 } catch (Exception e) { 365 // exception is acceptable 366 } finally { 367 hbt.shutdownMiniZKCluster(); 368 } 369 } 370 371 @Test public void testMiniDFSCluster() throws Exception { 372 HBaseTestingUtility hbt = new HBaseTestingUtility(); 373 MiniDFSCluster cluster = hbt.startMiniDFSCluster(null); 374 FileSystem dfs = cluster.getFileSystem(); 375 Path dir = new Path("dir"); 376 Path qualifiedDir = dfs.makeQualified(dir); 377 LOG.info("dir=" + dir + ", qualifiedDir=" + qualifiedDir); 378 assertFalse(dfs.exists(qualifiedDir)); 379 assertTrue(dfs.mkdirs(qualifiedDir)); 380 assertTrue(dfs.delete(qualifiedDir, true)); 381 hbt.shutdownMiniCluster(); 382 } 383 384 @Test public void testSetupClusterTestBuildDir() throws Exception { 385 HBaseTestingUtility hbt = new HBaseTestingUtility(); 386 Path testdir = hbt.getClusterTestDir(); 387 LOG.info("uuid-subdir=" + testdir); 388 FileSystem fs = hbt.getTestFileSystem(); 389 390 assertFalse(fs.exists(testdir)); 391 392 hbt.startMiniDFSCluster(null); 393 assertTrue(fs.exists(testdir)); 394 395 hbt.shutdownMiniCluster(); 396 assertFalse(fs.exists(testdir)); 397 } 398 399 @Test public void testTestDir() throws Exception { 400 HBaseTestingUtility hbt = new HBaseTestingUtility(); 401 Path testdir = hbt.getDataTestDir(); 402 LOG.info("testdir=" + testdir); 403 FileSystem fs = hbt.getTestFileSystem(); 404 assertTrue(!fs.exists(testdir)); 405 assertTrue(fs.mkdirs(testdir)); 406 assertTrue(hbt.cleanupTestDir()); 407 } 408 409 @Test public void testResolvePortConflict() throws Exception { 410 // raises port conflict between 1st call and 2nd call of randomPort() by mocking Random object 411 Random random = mock(Random.class); 412 when(random.nextInt(anyInt())) 413 .thenAnswer(new Answer<Integer>() { 414 int[] numbers = { 1, 1, 2 }; 415 int count = 0; 416 417 @Override 418 public Integer answer(InvocationOnMock invocation) { 419 int ret = numbers[count]; 420 count++; 421 return ret; 422 } 423 }); 424 425 HBaseTestingUtility.PortAllocator.AvailablePortChecker portChecker = 426 mock(HBaseTestingUtility.PortAllocator.AvailablePortChecker.class); 427 when(portChecker.available(anyInt())).thenReturn(true); 428 429 HBaseTestingUtility.PortAllocator portAllocator = 430 new HBaseTestingUtility.PortAllocator(random, portChecker); 431 432 int port1 = portAllocator.randomFreePort(); 433 int port2 = portAllocator.randomFreePort(); 434 assertNotEquals(port1, port2); 435 Mockito.verify(random, Mockito.times(3)).nextInt(anyInt()); 436 } 437 438 @Test 439 public void testOverridingOfDefaultPorts() throws Exception { 440 441 // confirm that default port properties being overridden to random 442 Configuration defaultConfig = HBaseConfiguration.create(); 443 defaultConfig.setInt(HConstants.MASTER_INFO_PORT, HConstants.DEFAULT_MASTER_INFOPORT); 444 defaultConfig.setInt(HConstants.REGIONSERVER_INFO_PORT, 445 HConstants.DEFAULT_REGIONSERVER_INFOPORT); 446 HBaseTestingUtility htu = new HBaseTestingUtility(defaultConfig); 447 try { 448 MiniHBaseCluster defaultCluster = htu.startMiniCluster(); 449 assertNotEquals(HConstants.DEFAULT_MASTER_INFOPORT, 450 defaultCluster.getConfiguration().getInt(HConstants.MASTER_INFO_PORT, 0)); 451 assertNotEquals(HConstants.DEFAULT_REGIONSERVER_INFOPORT, 452 defaultCluster.getConfiguration().getInt(HConstants.REGIONSERVER_INFO_PORT, 0)); 453 } finally { 454 htu.shutdownMiniCluster(); 455 } 456 457 // confirm that nonDefault (custom) port settings are NOT overridden 458 Configuration altConfig = HBaseConfiguration.create(); 459 final int nonDefaultMasterInfoPort = 3333; 460 final int nonDefaultRegionServerPort = 4444; 461 altConfig.setInt(HConstants.MASTER_INFO_PORT, nonDefaultMasterInfoPort); 462 altConfig.setInt(HConstants.REGIONSERVER_INFO_PORT, nonDefaultRegionServerPort); 463 htu = new HBaseTestingUtility(altConfig); 464 try { 465 MiniHBaseCluster customCluster = htu.startMiniCluster(); 466 assertEquals(nonDefaultMasterInfoPort, 467 customCluster.getConfiguration().getInt(HConstants.MASTER_INFO_PORT, 0)); 468 assertEquals(nonDefaultRegionServerPort, 469 customCluster.getConfiguration().getInt(HConstants.REGIONSERVER_INFO_PORT, 0)); 470 } finally { 471 htu.shutdownMiniCluster(); 472 } 473 } 474}