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