/* * Copyright (C) 2015 The Async HBase Authors. All rights reserved. * This file is part of Async HBase. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the StumbleUpon nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package org.hbase.async; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; import static org.mockito.Mockito.verify; import java.util.ArrayList; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.Channels; import org.junit.Before; import org.junit.Test; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.reflect.Whitebox; import com.stumbleupon.async.Deferred; import com.stumbleupon.async.TimeoutException; @PrepareForTest({ Channels.class, SecureRpcHelper.class, RegionClient.class }) public class TestRegionClientSendRpc extends BaseTestRegionClient { private static final byte[] QUALIFIER = new byte[] { 'Q', 'A', 'L' }; private static final byte[] VALUE = new byte[] { 42 }; @Before public void beforeLocal() throws Exception { when(hbase_client.getDefaultRpcTimeout()).thenReturn(60000); PowerMockito.mockStatic(Channels.class); timer.stop(); } @Test (expected = NullPointerException.class) public void nullRpc() throws Exception { region_client.sendRpc(null); } @Test public void putBatched() throws Exception { when(hbase_client.getFlushInterval()).thenReturn((short)1000); final PutRequest put = new PutRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); put.region = region; final Deferred<Object> deferred = put.getDeferred(); region_client.sendRpc(put); try { deferred.join(1); } catch (TimeoutException e) { } final MultiAction batched_rpcs = Whitebox.getInternalState(region_client, "batched_rpcs"); assertNotNull(batched_rpcs); assertEquals(1, batched_rpcs.size()); PowerMockito.verifyStatic(never()); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(put); assertEquals(0, rpcs_inflight.size()); assertEquals(0, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().writesBlocked()); assertEquals(1, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); assertEquals(0, timer.tasks.size()); } @Test public void putNoFlushing() throws Exception { final PutRequest put = new PutRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); put.region = region; final Deferred<Object> deferred = put.getDeferred(); region_client.sendRpc(put); try { deferred.join(1); } catch (TimeoutException e) { } final MultiAction batched_rpcs = Whitebox.getInternalState(region_client, "batched_rpcs"); assertNull(batched_rpcs); PowerMockito.verifyStatic(times(1)); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(put); assertEquals(1, rpcs_inflight.size()); assertEquals(1, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().writesBlocked()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); assertEquals(1, timer.tasks.size()); assertEquals(60000, (long)timer.tasks.get(0).getValue()); verify(timer.timeouts.get(0), never()).cancel(); } @Test public void putBatchDisabled() throws Exception { final PutRequest put = new PutRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); put.region = region; put.setBufferable(false); final Deferred<Object> deferred = put.getDeferred(); region_client.sendRpc(put); try { deferred.join(1); } catch (TimeoutException e) { } final MultiAction batched_rpcs = Whitebox.getInternalState(region_client, "batched_rpcs"); assertNull(batched_rpcs); PowerMockito.verifyStatic(times(1)); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(put); assertEquals(1, rpcs_inflight.size()); assertEquals(1, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().writesBlocked()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); assertEquals(1, timer.tasks.size()); assertEquals(60000, (long)timer.tasks.get(0).getValue()); verify(timer.timeouts.get(0), never()).cancel(); } @Test public void appendBatched() throws Exception { when(hbase_client.getFlushInterval()).thenReturn((short)1000); final AppendRequest append = new AppendRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); append.region = region; final Deferred<Object> deferred = append.getDeferred(); region_client.sendRpc(append); try { deferred.join(1); } catch (TimeoutException e) { } final MultiAction batched_rpcs = Whitebox.getInternalState(region_client, "batched_rpcs"); assertNotNull(batched_rpcs); assertEquals(1, batched_rpcs.size()); PowerMockito.verifyStatic(never()); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(append); assertEquals(0, rpcs_inflight.size()); assertEquals(0, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().writesBlocked()); assertEquals(1, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); assertEquals(0, timer.tasks.size()); } @Test public void appendNoFlushing() throws Exception { final AppendRequest append = new AppendRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); append.region = region; final Deferred<Object> deferred = append.getDeferred(); region_client.sendRpc(append); try { deferred.join(1); } catch (TimeoutException e) { } final MultiAction batched_rpcs = Whitebox.getInternalState(region_client, "batched_rpcs"); assertNull(batched_rpcs); PowerMockito.verifyStatic(times(1)); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(append); assertEquals(1, rpcs_inflight.size()); assertEquals(1, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().writesBlocked()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); assertEquals(1, timer.tasks.size()); assertEquals(60000, (long)timer.tasks.get(0).getValue()); verify(timer.timeouts.get(0), never()).cancel(); } @Test public void appendBatchDisabled() throws Exception { final AppendRequest append = new AppendRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); append.region = region; append.setBufferable(false); final Deferred<Object> deferred = append.getDeferred(); region_client.sendRpc(append); try { deferred.join(1); } catch (TimeoutException e) { } final MultiAction batched_rpcs = Whitebox.getInternalState(region_client, "batched_rpcs"); assertNull(batched_rpcs); PowerMockito.verifyStatic(times(1)); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(append); assertEquals(1, rpcs_inflight.size()); assertEquals(1, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().writesBlocked()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); assertEquals(1, timer.tasks.size()); assertEquals(60000, (long)timer.tasks.get(0).getValue()); verify(timer.timeouts.get(0), never()).cancel(); } @Test public void getRequest() throws Exception { final GetRequest get = new GetRequest(TABLE, KEY, FAMILY, QUALIFIER); get.setRegion(region); get.getDeferred(); // required to initialize the deferred region_client.sendRpc(get); PowerMockito.verifyStatic(times(1)); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(get); assertEquals(1, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); } @Test public void getRequestNoTimeout() throws Exception { final GetRequest get = new GetRequest(TABLE, KEY, FAMILY, QUALIFIER); get.setRegion(region); get.setTimeout(0); get.getDeferred(); // required to initialize the deferred region_client.sendRpc(get); PowerMockito.verifyStatic(times(1)); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(get); assertEquals(1, rpcs_inflight.size()); assertEquals(1, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().writesBlocked()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); assertEquals(0, timer.tasks.size()); } @Test public void getRequestCustomTimeout() throws Exception { final GetRequest get = new GetRequest(TABLE, KEY, FAMILY, QUALIFIER); get.setRegion(region); get.setTimeout(42000); get.getDeferred(); // required to initialize the deferred region_client.sendRpc(get); PowerMockito.verifyStatic(times(1)); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(get); assertEquals(1, rpcs_inflight.size()); assertEquals(1, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().writesBlocked()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); assertEquals(1, timer.tasks.size()); assertEquals(42000, (long)timer.tasks.get(0).getValue()); verify(timer.timeouts.get(0), never()).cancel(); } @Test (expected = AssertionError.class) public void getRequestUninitializedDeferred() throws Exception { final GetRequest get = new GetRequest(TABLE, KEY, FAMILY, QUALIFIER); region_client.sendRpc(get); } @Test public void getRequestBlockedWriteIgnoreState() throws Exception { when(chan.isWritable()).thenReturn(false); final GetRequest get = new GetRequest(TABLE, KEY, FAMILY, QUALIFIER); get.setRegion(region); get.getDeferred(); region_client.sendRpc(get); PowerMockito.verifyStatic(times(1)); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(get); assertEquals(1, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().writesBlocked()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); } @Test public void getRequestBlockedWrite() throws Exception { when(chan.isWritable()).thenReturn(false); Whitebox.setInternalState(region_client, "check_write_status", true); final GetRequest get = new GetRequest(TABLE, KEY, FAMILY, QUALIFIER); get.setRegion(region); final Deferred<Object> deferred = get.getDeferred(); region_client.sendRpc(get); PowerMockito.verifyStatic(never()); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(get); assertEquals(0, region_client.stats().rpcsSent()); assertEquals(1, region_client.stats().writesBlocked()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); try { deferred.join(); fail("Expected a PleaseThrottleException"); } catch (PleaseThrottleException e) { } } @Test public void multiAction() throws Exception { final Counter counter = new Counter(); Whitebox.setInternalState(hbase_client, "num_multi_rpcs", counter); final MultiAction ma = new MultiAction(); final PutRequest put1 = new PutRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); put1.setRegion(region); ma.add(put1); final PutRequest put2 = new PutRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); put2.setRegion(region); ma.add(put2); final Deferred<Object> deferred = ma.getDeferred(); region_client.sendRpc(ma); Exception ex = null; try { deferred.join(1); } catch (Exception e) { ex = e; } assertTrue(ex instanceof TimeoutException); PowerMockito.verifyStatic(times(1)); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(ma); assertEquals(1, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); assertEquals(1, counter.get()); } @Test public void multiActionToSingle() throws Exception { final Counter counter = new Counter(); Whitebox.setInternalState(hbase_client, "num_multi_rpcs", counter); final MultiAction ma = new MultiAction(); final PutRequest put1 = new PutRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); put1.setRegion(region); ma.add(put1); final Deferred<Object> deferred = ma.getDeferred(); region_client.sendRpc(ma); Exception ex = null; try { deferred.join(1); } catch (Exception e) { ex = e; } assertTrue(ex instanceof TimeoutException); PowerMockito.verifyStatic(times(1)); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(ma); assertEquals(1, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); assertEquals(0, counter.get()); } // Throws an NPE when it tries to serialize the action @Test public void multiActionEmpty() throws Exception { final Counter counter = new Counter(); Whitebox.setInternalState(hbase_client, "num_multi_rpcs", counter); final MultiAction ma = new MultiAction(); final Deferred<Object> deferred = ma.getDeferred(); region_client.sendRpc(ma); Exception ex = null; try { deferred.join(1); } catch (Exception e) { ex = e; } assertTrue(ex instanceof NullPointerException); PowerMockito.verifyStatic(never()); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(ma); assertEquals(0, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); assertEquals(1, counter.get()); } @Test public void nullChannelPut() throws Exception { Whitebox.setInternalState(region_client, "chan", (Channel)null); final PutRequest put = new PutRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); final Deferred<Object> deferred = put.getDeferred(); region_client.sendRpc(put); Exception ex = null; try { deferred.join(1); } catch (Exception e) { ex = e; } assertTrue(ex instanceof TimeoutException); PowerMockito.verifyStatic(never()); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(put); assertEquals(0, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(1, region_client.stats().pendingRPCs()); } @Test public void nullChannelPutDead() throws Exception { Whitebox.setInternalState(region_client, "chan", (Channel)null); Whitebox.setInternalState(region_client, "dead", true); final PutRequest put = new PutRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); put.setRegion(region); final Deferred<Object> deferred = put.getDeferred(); region_client.sendRpc(put); Exception ex = null; try { deferred.join(1); } catch (Exception e) { ex = e; } assertTrue(ex instanceof TimeoutException); PowerMockito.verifyStatic(never()); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, times(1)).sendRpcToRegion(put); assertEquals(0, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); } @Test public void nullChannelPutDeadNullRegion() throws Exception { Whitebox.setInternalState(region_client, "chan", (Channel)null); Whitebox.setInternalState(region_client, "dead", true); final PutRequest put = new PutRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); final Deferred<Object> deferred = put.getDeferred(); region_client.sendRpc(put); Exception ex = null; try { deferred.join(1); } catch (Exception e) { ex = e; } assertTrue(ex instanceof ConnectionResetException); PowerMockito.verifyStatic(never()); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(put); assertEquals(0, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); } @Test public void nullChannelPutDeadFailFast() throws Exception { Whitebox.setInternalState(region_client, "chan", (Channel)null); Whitebox.setInternalState(region_client, "dead", true); final PutRequest put = new PutRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); put.setRegion(region); put.setFailfast(true); final Deferred<Object> deferred = put.getDeferred(); region_client.sendRpc(put); Exception ex = null; try { deferred.join(1); } catch (Exception e) { ex = e; } assertTrue(ex instanceof ConnectionResetException); PowerMockito.verifyStatic(never()); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(put); assertEquals(0, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); } @Test public void wrap() throws Exception { final SecureRpcHelper helper = mock(SecureRpcHelper.class); Whitebox.setInternalState(region_client, "secure_rpc_helper", helper); doAnswer(new Answer<ChannelBuffer>() { @Override public ChannelBuffer answer(final InvocationOnMock invocation) throws Throwable { return ChannelBuffers.wrappedBuffer(new byte[]{ 42 }); } }).when(helper).wrap(any(ChannelBuffer.class)); final GetRequest get = new GetRequest(TABLE, KEY, FAMILY, QUALIFIER); get.setRegion(region); get.getDeferred(); // required to initialize the deferred region_client.sendRpc(get); PowerMockito.verifyStatic(times(1)); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(get); assertEquals(1, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); verify(helper, times(1)).wrap(any(ChannelBuffer.class)); } @Test public void pendingBreached() throws Exception { Whitebox.setInternalState(region_client, "pending_limit", 1); Whitebox.setInternalState(region_client, "chan", (Channel)null); final ArrayList<HBaseRpc> pending_rpcs = new ArrayList<HBaseRpc>(1); pending_rpcs.add(new GetRequest(TABLE, KEY, FAMILY)); Whitebox.setInternalState(region_client, "pending_rpcs", pending_rpcs); final PutRequest put = new PutRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); put.region = region; final Deferred<Object> deferred = put.getDeferred(); region_client.sendRpc(put); try { deferred.join(1); } catch (PleaseThrottleException e) { } final MultiAction batched_rpcs = Whitebox.getInternalState(region_client, "batched_rpcs"); assertNull(batched_rpcs); PowerMockito.verifyStatic(never()); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(put); assertEquals(0, rpcs_inflight.size()); assertEquals(0, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().writesBlocked()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(1, region_client.stats().pendingRPCs()); assertEquals(1, region_client.stats().pendingBreached()); assertEquals(0, timer.tasks.size()); } @Test public void inflightBreached() throws Exception { Whitebox.setInternalState(region_client, "inflight_limit", 1); rpcs_inflight.put(1, new GetRequest(TABLE, KEY, FAMILY)); final PutRequest put = new PutRequest(TABLE, KEY, FAMILY, QUALIFIER, VALUE); put.setBufferable(false); put.region = region; final Deferred<Object> deferred = put.getDeferred(); region_client.sendRpc(put); try { deferred.join(1); } catch (PleaseThrottleException e) { } final MultiAction batched_rpcs = Whitebox.getInternalState(region_client, "batched_rpcs"); assertNull(batched_rpcs); PowerMockito.verifyStatic(never()); Channels.write((Channel)any(), (ChannelBuffer)any()); verify(hbase_client, never()).sendRpcToRegion(put); assertEquals(1, rpcs_inflight.size()); assertEquals(0, region_client.stats().rpcsSent()); assertEquals(0, region_client.stats().writesBlocked()); assertEquals(0, region_client.stats().pendingBatchedRPCs()); assertEquals(0, region_client.stats().pendingRPCs()); assertEquals(0, region_client.stats().pendingBreached()); assertEquals(1, region_client.stats().inflightBreached()); assertEquals(0, timer.tasks.size()); } }