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.master.procedure; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertFalse; 022import static org.junit.Assert.assertThrows; 023import static org.junit.Assert.assertTrue; 024 025import java.io.IOException; 026import java.util.Optional; 027import java.util.concurrent.Future; 028import org.apache.hadoop.hbase.HBaseClassTestRule; 029import org.apache.hadoop.hbase.HBaseTestingUtil; 030import org.apache.hadoop.hbase.ServerName; 031import org.apache.hadoop.hbase.master.assignment.MockMasterServices; 032import org.apache.hadoop.hbase.procedure2.RemoteProcedureDispatcher; 033import org.apache.hadoop.hbase.testclassification.MasterTests; 034import org.apache.hadoop.hbase.testclassification.MediumTests; 035import org.junit.After; 036import org.junit.Before; 037import org.junit.ClassRule; 038import org.junit.Rule; 039import org.junit.Test; 040import org.junit.experimental.categories.Category; 041import org.junit.rules.TestName; 042import org.slf4j.Logger; 043import org.slf4j.LoggerFactory; 044 045@Category({ MasterTests.class, MediumTests.class }) 046public class TestReloadQuotasProcedure { 047 private static final Logger LOG = LoggerFactory.getLogger(TestReloadQuotasProcedure.class); 048 049 @ClassRule 050 public static final HBaseClassTestRule CLASS_RULE = 051 HBaseClassTestRule.forClass(TestReloadQuotasProcedure.class); 052 053 @Rule 054 public TestName name = new TestName(); 055 056 private HBaseTestingUtil util; 057 private MockMasterServices master; 058 private TestServerRemoteProcedure.MockRSProcedureDispatcher rsDispatcher; 059 060 @Before 061 public void setUp() throws Exception { 062 util = new HBaseTestingUtil(); 063 master = new MockMasterServices(util.getConfiguration()); 064 rsDispatcher = new TestServerRemoteProcedure.MockRSProcedureDispatcher(master); 065 master.start(2, rsDispatcher); 066 } 067 068 @After 069 public void tearDown() throws Exception { 070 master.stop("tearDown"); 071 } 072 073 @Test 074 public void itHandlesClassNotFoundExceptionGracefully() throws Exception { 075 ServerName targetServer = master.getServerManager().getOnlineServersList().get(0); 076 ReloadQuotasProcedure procedure = new ReloadQuotasProcedure(targetServer); 077 078 ClassNotFoundException classNotFound = 079 new ClassNotFoundException("ReloadQuotasCallable not found"); 080 IOException wrappedException = new IOException("Remote call failed", classNotFound); 081 082 boolean result = 083 procedure.complete(master.getMasterProcedureExecutor().getEnvironment(), wrappedException); 084 085 assertTrue(result); 086 } 087 088 @Test 089 public void itReturnsFailureForOtherExceptions() throws Exception { 090 ServerName targetServer = master.getServerManager().getOnlineServersList().get(0); 091 ReloadQuotasProcedure procedure = new ReloadQuotasProcedure(targetServer); 092 093 IOException otherException = new IOException("Some other error"); 094 095 boolean result = 096 procedure.complete(master.getMasterProcedureExecutor().getEnvironment(), otherException); 097 098 assertFalse(result); 099 } 100 101 @Test 102 public void itReturnsSuccessForNoError() throws Exception { 103 ServerName targetServer = master.getServerManager().getOnlineServersList().get(0); 104 ReloadQuotasProcedure procedure = new ReloadQuotasProcedure(targetServer); 105 106 boolean result = procedure.complete(master.getMasterProcedureExecutor().getEnvironment(), null); 107 108 assertTrue(result); 109 } 110 111 @Test 112 public void itCorrectlyDetectsCauseClass() { 113 ReloadQuotasProcedure procedure = new ReloadQuotasProcedure(); 114 115 ClassNotFoundException classNotFound = new ClassNotFoundException("test"); 116 IOException wrappedException = new IOException("wrapper", classNotFound); 117 RuntimeException outerWrapper = new RuntimeException("outer", wrappedException); 118 119 assertTrue(procedure.containsCause(outerWrapper, ClassNotFoundException.class)); 120 assertFalse(procedure.containsCause(outerWrapper, IllegalArgumentException.class)); 121 assertTrue(procedure.containsCause(classNotFound, ClassNotFoundException.class)); 122 } 123 124 @Test 125 public void itValidatesServerNameInRemoteCallBuild() throws Exception { 126 ServerName targetServer = master.getServerManager().getOnlineServersList().get(0); 127 ServerName wrongServer = master.getServerManager().getOnlineServersList().get(1); 128 ReloadQuotasProcedure procedure = new ReloadQuotasProcedure(targetServer); 129 130 MasterProcedureEnv env = master.getMasterProcedureExecutor().getEnvironment(); 131 132 Optional<RemoteProcedureDispatcher.RemoteOperation> result = 133 procedure.remoteCallBuild(env, targetServer); 134 assertTrue(result.isPresent()); 135 assertTrue(result.get() instanceof RSProcedureDispatcher.ServerOperation); 136 137 assertThrows(IllegalArgumentException.class, () -> { 138 procedure.remoteCallBuild(env, wrongServer); 139 }); 140 } 141 142 @Test 143 public void itCreatesCorrectRemoteOperation() throws Exception { 144 ServerName targetServer = master.getServerManager().getOnlineServersList().get(0); 145 ReloadQuotasProcedure procedure = new ReloadQuotasProcedure(targetServer); 146 MasterProcedureEnv env = master.getMasterProcedureExecutor().getEnvironment(); 147 148 Optional<RemoteProcedureDispatcher.RemoteOperation> operation = 149 procedure.remoteCallBuild(env, targetServer); 150 151 assertTrue(operation.isPresent()); 152 RSProcedureDispatcher.ServerOperation serverOp = 153 (RSProcedureDispatcher.ServerOperation) operation.get(); 154 assertEquals(serverOp.getRemoteProcedure(), procedure); 155 assertEquals(serverOp.buildRequest().getProcId(), procedure.getProcId()); 156 } 157 158 @Test 159 public void itThrowsUnsupportedOperationExceptionOnRollback() throws Exception { 160 ServerName targetServer = master.getServerManager().getOnlineServersList().get(0); 161 ReloadQuotasProcedure procedure = new ReloadQuotasProcedure(targetServer); 162 MasterProcedureEnv env = master.getMasterProcedureExecutor().getEnvironment(); 163 164 assertThrows(UnsupportedOperationException.class, () -> { 165 procedure.rollback(env); 166 }); 167 } 168 169 @Test 170 public void itReturnsFalseOnAbort() throws Exception { 171 ServerName targetServer = master.getServerManager().getOnlineServersList().get(0); 172 ReloadQuotasProcedure procedure = new ReloadQuotasProcedure(targetServer); 173 MasterProcedureEnv env = master.getMasterProcedureExecutor().getEnvironment(); 174 175 boolean result = procedure.abort(env); 176 177 assertFalse(result); 178 } 179 180 private Future<byte[]> submitProcedure(ReloadQuotasProcedure procedure) { 181 return ProcedureSyncWait.submitProcedure(master.getMasterProcedureExecutor(), procedure); 182 } 183}