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.client; 019 020import java.io.IOException; 021import java.util.Optional; 022import java.util.concurrent.atomic.AtomicLong; 023import org.apache.hadoop.conf.Configuration; 024import org.apache.hadoop.hbase.HRegionLocation; 025import org.apache.hadoop.hbase.RegionLocations; 026import org.apache.hadoop.hbase.ServerName; 027import org.apache.hadoop.hbase.TableName; 028import org.apache.hadoop.hbase.ZooKeeperConnectionException; 029import org.apache.hadoop.hbase.coprocessor.ObserverContext; 030import org.apache.hadoop.hbase.coprocessor.RegionCoprocessor; 031import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; 032import org.apache.hadoop.hbase.coprocessor.RegionObserver; 033import org.apache.hadoop.hbase.ipc.RpcControllerFactory; 034import org.apache.hadoop.hbase.util.Threads; 035import org.mockito.Mockito; 036 037import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos; 038import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos; 039 040/** 041 * {@link Connection} testing utility. 042 */ 043public class HConnectionTestingUtility { 044 /* 045 * Not part of {@link HBaseTestingUtility} because this class is not in same package as {@link 046 * ClusterConnection}. Would have to reveal ugly {@link ConnectionImplementation} innards to 047 * HBaseTestingUtility to give it access. 048 */ 049 /** 050 * <<<<<<< HEAD Get a Mocked {@link ClusterConnection} that goes with the passed <code>conf</code> 051 * configuration instance. Minimally the mock will return <code>conf</conf> when 052 * {@link ClusterConnection#getConfiguration()} is invoked. Be sure to shutdown the connection 053 * when done by calling {@link Connection#close()} else it will stick around; this is probably not 054 * what you want. ======= Get a Mocked {@link Connection} that goes with the passed 055 * <code>conf</code> configuration instance. Minimally the mock will return 056 * <code>conf</conf> when {@link Connection#getConfiguration()} is invoked. Be sure to 057 * shutdown the connection when done by calling {@link Connection#close()} else it will stick 058 * around; this is probably not what you want. >>>>>>> fabf2b8282... HBASE-22572 Javadoc 059 * Warnings: @link reference not found (#306) 060 * @param conf configuration 061 * @return ClusterConnection object for <code>conf</code> n 062 */ 063 public static ClusterConnection getMockedConnection(final Configuration conf) 064 throws ZooKeeperConnectionException { 065 ConnectionImplementation connection = Mockito.mock(ConnectionImplementation.class); 066 Mockito.when(connection.getConfiguration()).thenReturn(conf); 067 Mockito.when(connection.getRpcControllerFactory()) 068 .thenReturn(Mockito.mock(RpcControllerFactory.class)); 069 // we need a real retrying caller 070 RpcRetryingCallerFactory callerFactory = new RpcRetryingCallerFactory(conf); 071 Mockito.when(connection.getRpcRetryingCallerFactory()).thenReturn(callerFactory); 072 return connection; 073 } 074 075 /** 076 * Calls {@link #getMockedConnection(Configuration)} and then mocks a few more of the popular 077 * {@link ClusterConnection} methods so they do 'normal' operation (see return doc below for 078 * list). Be sure to shutdown the connection when done by calling {@link Connection#close()} else 079 * it will stick around; this is probably not what you want. 080 * @param conf Configuration to use 081 * @param admin An AdminProtocol; can be null but is usually itself a mock. 082 * @param client A ClientProtocol; can be null but is usually itself a mock. 083 * @param sn ServerName to include in the region location returned by this 084 * <code>connection</code> 085 * @param hri RegionInfo to include in the location returned when getRegionLocator is called on 086 * the mocked connection 087 * @return Mock up a connection that returns a {@link Configuration} when 088 * {@link ClusterConnection#getConfiguration()} is called, a 'location' when 089 * {@link ClusterConnection#getRegionLocation(org.apache.hadoop.hbase.TableName, byte[], boolean)} 090 * is called, and that returns the passed 091 * {@link AdminProtos.AdminService.BlockingInterface} instance when 092 * {@link ClusterConnection#getAdmin(ServerName)} is called, returns the passed 093 * {@link ClientProtos.ClientService.BlockingInterface} instance when 094 * {@link ClusterConnection#getClient(ServerName)} is called (Be sure to call 095 * {@link Connection#close()} when done with this mocked Connection. n 096 */ 097 public static ClusterConnection getMockedConnectionAndDecorate(final Configuration conf, 098 final AdminProtos.AdminService.BlockingInterface admin, 099 final ClientProtos.ClientService.BlockingInterface client, final ServerName sn, 100 final RegionInfo hri) throws IOException { 101 ConnectionImplementation c = Mockito.mock(ConnectionImplementation.class); 102 Mockito.when(c.getConfiguration()).thenReturn(conf); 103 ConnectionConfiguration connectionConfiguration = new ConnectionConfiguration(conf); 104 Mockito.when(c.getConnectionConfiguration()).thenReturn(connectionConfiguration); 105 Mockito.doNothing().when(c).close(); 106 // Make it so we return a particular location when asked. 107 final HRegionLocation loc = new HRegionLocation(hri, sn); 108 Mockito.when( 109 c.getRegionLocation((TableName) Mockito.any(), (byte[]) Mockito.any(), Mockito.anyBoolean())) 110 .thenReturn(loc); 111 Mockito.when(c.locateRegion((TableName) Mockito.any(), (byte[]) Mockito.any())).thenReturn(loc); 112 Mockito.when(c.locateRegion((TableName) Mockito.any(), (byte[]) Mockito.any(), 113 Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.anyInt())) 114 .thenReturn(new RegionLocations(loc)); 115 if (admin != null) { 116 // If a call to getAdmin, return this implementation. 117 Mockito.when(c.getAdmin(Mockito.any())).thenReturn(admin); 118 } 119 if (client != null) { 120 // If a call to getClient, return this client. 121 Mockito.when(c.getClient(Mockito.any())).thenReturn(client); 122 } 123 NonceGenerator ng = Mockito.mock(NonceGenerator.class); 124 Mockito.when(c.getNonceGenerator()).thenReturn(ng); 125 AsyncProcess asyncProcess = new AsyncProcess(c, conf, 126 RpcRetryingCallerFactory.instantiate(conf), RpcControllerFactory.instantiate(conf)); 127 Mockito.when(c.getAsyncProcess()).thenReturn(asyncProcess); 128 Mockito.when(c.getNewRpcRetryingCallerFactory(conf)).thenReturn(RpcRetryingCallerFactory 129 .instantiate(conf, RetryingCallerInterceptorFactory.NO_OP_INTERCEPTOR, null)); 130 Mockito.when(c.getRpcControllerFactory()).thenReturn(Mockito.mock(RpcControllerFactory.class)); 131 Table t = Mockito.mock(Table.class); 132 Mockito.when(c.getTable((TableName) Mockito.any())).thenReturn(t); 133 ResultScanner rs = Mockito.mock(ResultScanner.class); 134 Mockito.when(t.getScanner((Scan) Mockito.any())).thenReturn(rs); 135 return c; 136 } 137 138 /** 139 * Get a Mockito spied-upon {@link ClusterConnection} that goes with the passed <code>conf</code> 140 * configuration instance. Be sure to shutdown the connection when done by calling 141 * {@link Connection#close()} else it will stick around; this is probably not what you want. 142 * @param conf configuration 143 * @return ClusterConnection object for <code>conf</code> n * [Dead link]: See also 144 * {http://mockito.googlecode.com/svn/branches/1.6/javadoc/org/mockito/Mockito.html#spy(T)} 145 */ 146 public static ClusterConnection getSpiedConnection(final Configuration conf) throws IOException { 147 ConnectionImplementation connection = 148 Mockito.spy(new ConnectionImplementation(conf, null, null)); 149 return connection; 150 } 151 152 /** 153 * This coproceesor sleep 2s at first increment/append rpc call. 154 */ 155 public static class SleepAtFirstRpcCall implements RegionCoprocessor, RegionObserver { 156 static final AtomicLong ct = new AtomicLong(0); 157 static final String SLEEP_TIME_CONF_KEY = "hbase.coprocessor.SleepAtFirstRpcCall.sleepTime"; 158 static final long DEFAULT_SLEEP_TIME = 2000; 159 static final AtomicLong sleepTime = new AtomicLong(DEFAULT_SLEEP_TIME); 160 161 @Override 162 public Optional<RegionObserver> getRegionObserver() { 163 return Optional.of(this); 164 } 165 166 public SleepAtFirstRpcCall() { 167 } 168 169 @Override 170 public void postOpen(ObserverContext<RegionCoprocessorEnvironment> c) { 171 RegionCoprocessorEnvironment env = c.getEnvironment(); 172 Configuration conf = env.getConfiguration(); 173 sleepTime.set(conf.getLong(SLEEP_TIME_CONF_KEY, DEFAULT_SLEEP_TIME)); 174 } 175 176 @Override 177 public Result postIncrement(final ObserverContext<RegionCoprocessorEnvironment> e, 178 final Increment increment, final Result result) throws IOException { 179 if (ct.incrementAndGet() == 1) { 180 Threads.sleep(sleepTime.get()); 181 } 182 return result; 183 } 184 185 @Override 186 public Result postAppend(final ObserverContext<RegionCoprocessorEnvironment> e, 187 final Append append, final Result result) throws IOException { 188 if (ct.incrementAndGet() == 1) { 189 Threads.sleep(sleepTime.get()); 190 } 191 return result; 192 } 193 } 194}