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