| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.hadoop.hbase; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.mockito.ArgumentMatchers.anyInt; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.when; |
| import java.io.File; |
| import java.util.List; |
| import java.util.Random; |
| import org.apache.hadoop.conf.Configuration; |
| import org.apache.hadoop.fs.FileSystem; |
| import org.apache.hadoop.fs.FileUtil; |
| import org.apache.hadoop.fs.Path; |
| import org.apache.hadoop.hbase.client.Get; |
| import org.apache.hadoop.hbase.client.Put; |
| import org.apache.hadoop.hbase.client.Result; |
| import org.apache.hadoop.hbase.client.Table; |
| import org.apache.hadoop.hbase.http.ssl.KeyStoreTestUtil; |
| import org.apache.hadoop.hbase.testclassification.LargeTests; |
| import org.apache.hadoop.hbase.testclassification.MiscTests; |
| import org.apache.hadoop.hbase.util.Bytes; |
| import org.apache.hadoop.hbase.zookeeper.MiniZooKeeperCluster; |
| import org.apache.hadoop.hdfs.MiniDFSCluster; |
| import org.apache.hadoop.security.ssl.SSLFactory; |
| import org.junit.ClassRule; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.experimental.categories.Category; |
| import org.junit.rules.TestName; |
| import org.mockito.Mockito; |
| import org.mockito.invocation.InvocationOnMock; |
| import org.mockito.stubbing.Answer; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * Test our testing utility class |
| */ |
| @Category({MiscTests.class, LargeTests.class}) |
| public class TestHBaseTestingUtility { |
| private static final int NUMTABLES = 1; |
| private static final int NUMROWS = 100; |
| private static final int NUMREGIONS = 10; |
| |
| @ClassRule |
| public static final HBaseClassTestRule CLASS_RULE = |
| HBaseClassTestRule.forClass(TestHBaseTestingUtility.class); |
| |
| private static final Logger LOG = LoggerFactory.getLogger(TestHBaseTestingUtility.class); |
| |
| @Rule |
| public TestName name = new TestName(); |
| |
| /** |
| * Basic sanity test that spins up multiple HDFS and HBase clusters that share |
| * the same ZK ensemble. We then create the same table in both and make sure |
| * that what we insert in one place doesn't end up in the other. |
| * @throws Exception on error |
| */ |
| @Test |
| public void testMultiClusters() throws Exception { |
| // Create three clusters |
| |
| // Cluster 1. |
| HBaseTestingUtility htu1 = new HBaseTestingUtility(); |
| // Set a different zk path for each cluster |
| htu1.getConfiguration().set(HConstants.ZOOKEEPER_ZNODE_PARENT, "/1"); |
| htu1.startMiniZKCluster(); |
| |
| // Cluster 2 |
| HBaseTestingUtility htu2 = new HBaseTestingUtility(); |
| htu2.getConfiguration().set(HConstants.ZOOKEEPER_ZNODE_PARENT, "/2"); |
| htu2.getConfiguration().set(HConstants.ZOOKEEPER_CLIENT_PORT, |
| htu1.getConfiguration().get(HConstants.ZOOKEEPER_CLIENT_PORT, "-1")); |
| htu2.setZkCluster(htu1.getZkCluster()); |
| |
| // Cluster 3; seed it with the conf from htu1 so we pickup the 'right' |
| // zk cluster config; it is set back into the config. as part of the |
| // start of minizkcluster. |
| HBaseTestingUtility htu3 = new HBaseTestingUtility(); |
| htu3.getConfiguration().set(HConstants.ZOOKEEPER_ZNODE_PARENT, "/3"); |
| htu3.getConfiguration().set(HConstants.ZOOKEEPER_CLIENT_PORT, |
| htu1.getConfiguration().get(HConstants.ZOOKEEPER_CLIENT_PORT, "-1")); |
| htu3.setZkCluster(htu1.getZkCluster()); |
| |
| try { |
| htu1.startMiniCluster(); |
| htu2.startMiniCluster(); |
| htu3.startMiniCluster(); |
| |
| final TableName tableName = TableName.valueOf(name.getMethodName()); |
| final byte[] FAM_NAME = Bytes.toBytes("fam"); |
| final byte[] ROW = Bytes.toBytes("row"); |
| final byte[] QUAL_NAME = Bytes.toBytes("qual"); |
| final byte[] VALUE = Bytes.toBytes("value"); |
| |
| Table table1 = htu1.createTable(tableName, FAM_NAME); |
| Table table2 = htu2.createTable(tableName, FAM_NAME); |
| |
| Put put = new Put(ROW); |
| put.addColumn(FAM_NAME, QUAL_NAME, VALUE); |
| table1.put(put); |
| |
| Get get = new Get(ROW); |
| get.addColumn(FAM_NAME, QUAL_NAME); |
| Result res = table1.get(get); |
| assertEquals(1, res.size()); |
| |
| res = table2.get(get); |
| assertEquals(0, res.size()); |
| |
| table1.close(); |
| table2.close(); |
| |
| } finally { |
| htu3.shutdownMiniCluster(); |
| htu2.shutdownMiniCluster(); |
| htu1.shutdownMiniCluster(); |
| } |
| } |
| |
| @Test public void testMiniCluster() throws Exception { |
| HBaseTestingUtility hbt = new HBaseTestingUtility(); |
| |
| MiniHBaseCluster cluster = hbt.startMiniCluster(); |
| try { |
| assertEquals(1, cluster.getLiveRegionServerThreads().size()); |
| } finally { |
| hbt.shutdownMiniCluster(); |
| } |
| } |
| |
| @Test |
| public void testMiniClusterBindToWildcard() throws Exception { |
| HBaseTestingUtility hbt = new HBaseTestingUtility(); |
| hbt.getConfiguration().set("hbase.regionserver.ipc.address", "0.0.0.0"); |
| MiniHBaseCluster cluster = hbt.startMiniCluster(); |
| try { |
| assertEquals(1, cluster.getLiveRegionServerThreads().size()); |
| } finally { |
| hbt.shutdownMiniCluster(); |
| } |
| } |
| |
| @Test |
| public void testMiniClusterWithSSLOn() throws Exception { |
| final String BASEDIR = System.getProperty("test.build.dir", |
| "target/test-dir") + "/" + TestHBaseTestingUtility.class.getSimpleName(); |
| String sslConfDir = KeyStoreTestUtil.getClasspathDir(TestHBaseTestingUtility.class); |
| String keystoresDir = new File(BASEDIR).getAbsolutePath(); |
| |
| HBaseTestingUtility hbt = new HBaseTestingUtility(); |
| File base = new File(BASEDIR); |
| FileUtil.fullyDelete(base); |
| base.mkdirs(); |
| |
| KeyStoreTestUtil.setupSSLConfig(keystoresDir, sslConfDir, hbt.getConfiguration(), false); |
| |
| hbt.getConfiguration().set("hbase.ssl.enabled", "true"); |
| hbt.getConfiguration().addResource(hbt.getConfiguration().get(SSLFactory.SSL_CLIENT_CONF_KEY)); |
| hbt.getConfiguration().addResource(hbt.getConfiguration().get(SSLFactory.SSL_SERVER_CONF_KEY)); |
| |
| MiniHBaseCluster cluster = hbt.startMiniCluster(); |
| try { |
| assertEquals(1, cluster.getLiveRegionServerThreads().size()); |
| } finally { |
| hbt.shutdownMiniCluster(); |
| } |
| } |
| |
| /** |
| * Test that we can start and stop multiple time a cluster |
| * with the same HBaseTestingUtility. |
| */ |
| @Test public void testMultipleStartStop() throws Exception{ |
| HBaseTestingUtility htu1 = new HBaseTestingUtility(); |
| Path foo = new Path("foo"); |
| |
| htu1.startMiniCluster(); |
| htu1.getDFSCluster().getFileSystem().create(foo); |
| assertTrue(htu1.getDFSCluster().getFileSystem().exists(foo)); |
| htu1.shutdownMiniCluster(); |
| |
| htu1.startMiniCluster(); |
| assertFalse(htu1.getDFSCluster().getFileSystem().exists(foo)); |
| htu1.getDFSCluster().getFileSystem().create(foo); |
| assertTrue(htu1.getDFSCluster().getFileSystem().exists(foo)); |
| htu1.shutdownMiniCluster(); |
| } |
| |
| @Test |
| public void testMiniZooKeeperWithOneServer() throws Exception { |
| HBaseTestingUtility hbt = new HBaseTestingUtility(); |
| MiniZooKeeperCluster cluster1 = hbt.startMiniZKCluster(); |
| try { |
| assertEquals(0, cluster1.getBackupZooKeeperServerNum()); |
| assertTrue((cluster1.killCurrentActiveZooKeeperServer() == -1)); |
| } finally { |
| hbt.shutdownMiniZKCluster(); |
| } |
| } |
| |
| @Test |
| public void testMiniZooKeeperWithMultipleServers() throws Exception { |
| HBaseTestingUtility hbt = new HBaseTestingUtility(); |
| // set up zookeeper cluster with 5 zk servers |
| MiniZooKeeperCluster cluster2 = hbt.startMiniZKCluster(5); |
| int defaultClientPort = 21818; |
| cluster2.setDefaultClientPort(defaultClientPort); |
| try { |
| assertEquals(4, cluster2.getBackupZooKeeperServerNum()); |
| |
| // killing the current active zk server |
| int currentActivePort = cluster2.killCurrentActiveZooKeeperServer(); |
| assertTrue(currentActivePort >= defaultClientPort); |
| // Check if the client port is returning a proper value |
| assertTrue(cluster2.getClientPort() == currentActivePort); |
| |
| // kill another active zk server |
| currentActivePort = cluster2.killCurrentActiveZooKeeperServer(); |
| assertTrue(currentActivePort >= defaultClientPort); |
| assertTrue(cluster2.getClientPort() == currentActivePort); |
| assertEquals(2, cluster2.getBackupZooKeeperServerNum()); |
| assertEquals(3, cluster2.getZooKeeperServerNum()); |
| |
| // killing the backup zk servers |
| cluster2.killOneBackupZooKeeperServer(); |
| cluster2.killOneBackupZooKeeperServer(); |
| assertEquals(0, cluster2.getBackupZooKeeperServerNum()); |
| assertEquals(1, cluster2.getZooKeeperServerNum()); |
| |
| // killing the last zk server |
| currentActivePort = cluster2.killCurrentActiveZooKeeperServer(); |
| assertTrue(currentActivePort == -1); |
| assertTrue(cluster2.getClientPort() == currentActivePort); |
| // this should do nothing. |
| cluster2.killOneBackupZooKeeperServer(); |
| assertEquals(-1, cluster2.getBackupZooKeeperServerNum()); |
| assertEquals(0, cluster2.getZooKeeperServerNum()); |
| } finally { |
| hbt.shutdownMiniZKCluster(); |
| } |
| } |
| |
| @Test |
| public void testMiniZooKeeperWithMultipleClientPorts() throws Exception { |
| int defaultClientPort = 8888; |
| int i, j; |
| HBaseTestingUtility hbt = new HBaseTestingUtility(); |
| |
| // Test 1 - set up zookeeper cluster with same number of ZK servers and specified client ports |
| int [] clientPortList1 = {1111, 1112, 1113}; |
| MiniZooKeeperCluster cluster1 = hbt.startMiniZKCluster(clientPortList1.length, clientPortList1); |
| try { |
| List<Integer> clientPortListInCluster = cluster1.getClientPortList(); |
| |
| for (i = 0; i < clientPortListInCluster.size(); i++) { |
| // cannot assert the specific port due to the port conflict in which situation |
| // it always chooses a bigger port by +1. The below is the same. |
| assertTrue(clientPortListInCluster.get(i).intValue() >= clientPortList1[i]); |
| } |
| } finally { |
| hbt.shutdownMiniZKCluster(); |
| } |
| |
| // Test 2 - set up zookeeper cluster with more ZK servers than specified client ports |
| hbt.getConfiguration().setInt("test.hbase.zookeeper.property.clientPort", defaultClientPort); |
| int [] clientPortList2 = {2222, 2223}; |
| MiniZooKeeperCluster cluster2 = |
| hbt.startMiniZKCluster(clientPortList2.length + 2, clientPortList2); |
| |
| try { |
| List<Integer> clientPortListInCluster = cluster2.getClientPortList(); |
| |
| for (i = 0, j = 0; i < clientPortListInCluster.size(); i++) { |
| if (i < clientPortList2.length) { |
| assertTrue(clientPortListInCluster.get(i).intValue() >= clientPortList2[i]); |
| } else { |
| // servers with no specified client port will use defaultClientPort or some other ports |
| // based on defaultClientPort |
| assertTrue(clientPortListInCluster.get(i).intValue() >= defaultClientPort + j); |
| j++; |
| } |
| } |
| } finally { |
| hbt.shutdownMiniZKCluster(); |
| } |
| |
| // Test 3 - set up zookeeper cluster with invalid client ports |
| hbt.getConfiguration().setInt("test.hbase.zookeeper.property.clientPort", defaultClientPort); |
| int [] clientPortList3 = {3333, -3334, 3335, 0}; |
| MiniZooKeeperCluster cluster3 = |
| hbt.startMiniZKCluster(clientPortList3.length + 1, clientPortList3); |
| |
| try { |
| List<Integer> clientPortListInCluster = cluster3.getClientPortList(); |
| |
| for (i = 0, j = 0; i < clientPortListInCluster.size(); i++) { |
| // Servers will only use valid client ports; if ports are not specified or invalid, |
| // the default port or a port based on default port will be used. |
| if (i < clientPortList3.length && clientPortList3[i] > 0) { |
| assertTrue(clientPortListInCluster.get(i).intValue() >= clientPortList3[i]); |
| } else { |
| assertTrue(clientPortListInCluster.get(i).intValue() >= defaultClientPort + j); |
| j++; |
| } |
| } |
| } finally { |
| hbt.shutdownMiniZKCluster(); |
| } |
| |
| // Test 4 - set up zookeeper cluster with default port and some other ports used |
| // This test tests that the defaultClientPort and defaultClientPort+2 are used, so |
| // the algorithm should choice defaultClientPort+1 and defaultClientPort+3 to fill |
| // out the ports for servers without ports specified. |
| hbt.getConfiguration().setInt("test.hbase.zookeeper.property.clientPort", defaultClientPort); |
| int [] clientPortList4 = {-4444, defaultClientPort+2, 4446, defaultClientPort}; |
| MiniZooKeeperCluster cluster4 = |
| hbt.startMiniZKCluster(clientPortList4.length + 1, clientPortList4); |
| |
| try { |
| List<Integer> clientPortListInCluster = cluster4.getClientPortList(); |
| |
| for (i = 0, j = 1; i < clientPortListInCluster.size(); i++) { |
| // Servers will only use valid client ports; if ports are not specified or invalid, |
| // the default port or a port based on default port will be used. |
| if (i < clientPortList4.length && clientPortList4[i] > 0) { |
| assertTrue(clientPortListInCluster.get(i).intValue() >= clientPortList4[i]); |
| } else { |
| assertTrue(clientPortListInCluster.get(i).intValue() >= defaultClientPort + j); |
| j +=2; |
| } |
| } |
| } finally { |
| hbt.shutdownMiniZKCluster(); |
| } |
| |
| // Test 5 - set up zookeeper cluster with same ports specified - fail is expected. |
| int [] clientPortList5 = {5555, 5556, 5556}; |
| |
| try { |
| MiniZooKeeperCluster cluster5 = |
| hbt.startMiniZKCluster(clientPortList5.length, clientPortList5); |
| assertTrue(cluster5.getClientPort() == -1); // expected failure |
| } catch (Exception e) { |
| // exception is acceptable |
| } finally { |
| hbt.shutdownMiniZKCluster(); |
| } |
| } |
| |
| @Test public void testMiniDFSCluster() throws Exception { |
| HBaseTestingUtility hbt = new HBaseTestingUtility(); |
| MiniDFSCluster cluster = hbt.startMiniDFSCluster(null); |
| FileSystem dfs = cluster.getFileSystem(); |
| Path dir = new Path("dir"); |
| Path qualifiedDir = dfs.makeQualified(dir); |
| LOG.info("dir=" + dir + ", qualifiedDir=" + qualifiedDir); |
| assertFalse(dfs.exists(qualifiedDir)); |
| assertTrue(dfs.mkdirs(qualifiedDir)); |
| assertTrue(dfs.delete(qualifiedDir, true)); |
| hbt.shutdownMiniCluster(); |
| } |
| |
| @Test public void testSetupClusterTestBuildDir() throws Exception { |
| HBaseTestingUtility hbt = new HBaseTestingUtility(); |
| Path testdir = hbt.getClusterTestDir(); |
| LOG.info("uuid-subdir=" + testdir); |
| FileSystem fs = hbt.getTestFileSystem(); |
| |
| assertFalse(fs.exists(testdir)); |
| |
| hbt.startMiniDFSCluster(null); |
| assertTrue(fs.exists(testdir)); |
| |
| hbt.shutdownMiniCluster(); |
| assertFalse(fs.exists(testdir)); |
| } |
| |
| @Test public void testTestDir() throws Exception { |
| HBaseTestingUtility hbt = new HBaseTestingUtility(); |
| Path testdir = hbt.getDataTestDir(); |
| LOG.info("testdir=" + testdir); |
| FileSystem fs = hbt.getTestFileSystem(); |
| assertTrue(!fs.exists(testdir)); |
| assertTrue(fs.mkdirs(testdir)); |
| assertTrue(hbt.cleanupTestDir()); |
| } |
| |
| @Test public void testResolvePortConflict() throws Exception { |
| // raises port conflict between 1st call and 2nd call of randomPort() by mocking Random object |
| Random random = mock(Random.class); |
| when(random.nextInt(anyInt())) |
| .thenAnswer(new Answer<Integer>() { |
| int[] numbers = { 1, 1, 2 }; |
| int count = 0; |
| |
| @Override |
| public Integer answer(InvocationOnMock invocation) { |
| int ret = numbers[count]; |
| count++; |
| return ret; |
| } |
| }); |
| |
| HBaseTestingUtility.PortAllocator.AvailablePortChecker portChecker = |
| mock(HBaseTestingUtility.PortAllocator.AvailablePortChecker.class); |
| when(portChecker.available(anyInt())).thenReturn(true); |
| |
| HBaseTestingUtility.PortAllocator portAllocator = |
| new HBaseTestingUtility.PortAllocator(random, portChecker); |
| |
| int port1 = portAllocator.randomFreePort(); |
| int port2 = portAllocator.randomFreePort(); |
| assertNotEquals(port1, port2); |
| Mockito.verify(random, Mockito.times(3)).nextInt(anyInt()); |
| } |
| |
| @Test |
| public void testOverridingOfDefaultPorts() throws Exception { |
| |
| // confirm that default port properties being overridden to random |
| Configuration defaultConfig = HBaseConfiguration.create(); |
| defaultConfig.setInt(HConstants.MASTER_INFO_PORT, HConstants.DEFAULT_MASTER_INFOPORT); |
| defaultConfig.setInt(HConstants.REGIONSERVER_INFO_PORT, |
| HConstants.DEFAULT_REGIONSERVER_INFOPORT); |
| HBaseTestingUtility htu = new HBaseTestingUtility(defaultConfig); |
| try { |
| MiniHBaseCluster defaultCluster = htu.startMiniCluster(); |
| final String masterHostPort = |
| defaultCluster.getMaster().getServerName().getAddress().toString(); |
| assertNotEquals(HConstants.DEFAULT_MASTER_INFOPORT, |
| defaultCluster.getConfiguration().getInt(HConstants.MASTER_INFO_PORT, 0)); |
| assertNotEquals(HConstants.DEFAULT_REGIONSERVER_INFOPORT, |
| defaultCluster.getConfiguration().getInt(HConstants.REGIONSERVER_INFO_PORT, 0)); |
| assertEquals(masterHostPort, |
| defaultCluster.getConfiguration().get(HConstants.MASTER_ADDRS_KEY)); |
| } finally { |
| htu.shutdownMiniCluster(); |
| } |
| |
| // confirm that nonDefault (custom) port settings are NOT overridden |
| Configuration altConfig = HBaseConfiguration.create(); |
| final int nonDefaultMasterInfoPort = 3333; |
| final int nonDefaultRegionServerPort = 4444; |
| altConfig.setInt(HConstants.MASTER_INFO_PORT, nonDefaultMasterInfoPort); |
| altConfig.setInt(HConstants.REGIONSERVER_INFO_PORT, nonDefaultRegionServerPort); |
| htu = new HBaseTestingUtility(altConfig); |
| try { |
| MiniHBaseCluster customCluster = htu.startMiniCluster(); |
| final String masterHostPort = |
| customCluster.getMaster().getServerName().getAddress().toString(); |
| assertEquals(nonDefaultMasterInfoPort, |
| customCluster.getConfiguration().getInt(HConstants.MASTER_INFO_PORT, 0)); |
| assertEquals(nonDefaultRegionServerPort, |
| customCluster.getConfiguration().getInt(HConstants.REGIONSERVER_INFO_PORT, 0)); |
| assertEquals(masterHostPort, |
| customCluster.getConfiguration().get(HConstants.MASTER_ADDRS_KEY)); |
| } finally { |
| htu.shutdownMiniCluster(); |
| } |
| } |
| |
| // This test demonstrates how long killHBTU takes vs. shutdownHBTU takes |
| // for realistic results, adjust NUMROWS, NUMTABLES to much larger number. |
| @Test |
| public void testKillMiniHBaseCluster() throws Exception { |
| |
| HBaseTestingUtility htu = new HBaseTestingUtility(); |
| htu.startMiniZKCluster(); |
| |
| try { |
| htu.startMiniHBaseCluster(); |
| |
| TableName tableName; |
| byte[] FAM_NAME; |
| |
| for(int i = 0; i < NUMTABLES; i++) { |
| tableName = TableName.valueOf(name.getMethodName() + i); |
| FAM_NAME = Bytes.toBytes("fam" + i); |
| |
| try (Table table = htu.createMultiRegionTable(tableName, FAM_NAME, NUMREGIONS)) { |
| htu.loadRandomRows(table, FAM_NAME, 100, NUMROWS); |
| } |
| } |
| } finally { |
| htu.killMiniHBaseCluster(); |
| htu.shutdownMiniZKCluster(); |
| } |
| } |
| } |