View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.client.coprocessor;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertTrue;
22  import static org.mockito.Matchers.any;
23  import static org.mockito.Mockito.doAnswer;
24  import static org.mockito.Mockito.mock;
25  import static org.mockito.Mockito.when;
26  
27  import java.io.IOException;
28  import java.util.Collections;
29  
30  import org.apache.hadoop.hbase.DoNotRetryIOException;
31  import org.apache.hadoop.hbase.HConstants;
32  import org.apache.hadoop.hbase.TableName;
33  import org.apache.hadoop.hbase.client.Table;
34  import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
35  import org.apache.hadoop.hbase.ipc.ServerRpcController;
36  import org.apache.hadoop.hbase.protobuf.generated.SecureBulkLoadProtos.CleanupBulkLoadResponse;
37  import org.apache.hadoop.hbase.protobuf.generated.SecureBulkLoadProtos.PrepareBulkLoadResponse;
38  import org.apache.hadoop.hbase.protobuf.generated.SecureBulkLoadProtos.SecureBulkLoadHFilesResponse;
39  import org.apache.hadoop.hbase.testclassification.ClientTests;
40  import org.apache.hadoop.hbase.testclassification.SmallTests;
41  import org.apache.hadoop.hbase.util.Pair;
42  import org.apache.hadoop.util.StringUtils;
43  import org.junit.Before;
44  import org.junit.Test;
45  import org.junit.experimental.categories.Category;
46  import org.mockito.invocation.InvocationOnMock;
47  import org.mockito.stubbing.Answer;
48  
49  import com.google.protobuf.Descriptors.MethodDescriptor;
50  import com.google.protobuf.Message;
51  import com.google.protobuf.RpcCallback;
52  import com.google.protobuf.RpcController;
53  
54  /**
55   * Test class for the SecureBulkLoadClient.
56   */
57  @Category({ClientTests.class, SmallTests.class})
58  public class TestSecureBulkLoadClient {
59    private static final DoNotRetryIOException DNRIOE = new DoNotRetryIOException("Go away and don't come back");
60  
61    private CoprocessorRpcChannel rpcChannel;
62    private Table table;
63    private SecureBulkLoadClient client;
64  
65    @Before
66    public void setupMembers() {
67      rpcChannel = mock(CoprocessorRpcChannel.class);
68      table = mock(Table.class);
69      client = new SecureBulkLoadClient(table);
70  
71      // Mock out a Table to return a custom CoprocessorRpcChannel
72      when(table.coprocessorService(HConstants.EMPTY_START_ROW)).thenReturn(rpcChannel);
73    }
74  
75    /**
76     * Mocks an RPC to the SecureBulkLoadEndpoint.
77     *
78     * The provided {@code response} and {@code failureCause} are set such that the
79     * {@link SecureBulkLoadClient} thinks that they were sent by a RegionServer.
80     * The {@code expectedMethodName} verifies that the proper RPC method was
81     * invoked as a sanity check.
82     */
83    @SuppressWarnings("unchecked")
84    private void setupMockForMethod(
85        final String expectedMethodName, final Message response, final IOException failureCause) {
86      doAnswer(new Answer<Void>() {
87        @Override
88        public Void answer(InvocationOnMock invocation) throws Throwable {
89          MethodDescriptor method = invocation.getArgumentAt(0, MethodDescriptor.class);
90          ServerRpcController controller = invocation.getArgumentAt(1, ServerRpcController.class);
91          RpcCallback<Message> rpcCallback = invocation.getArgumentAt(4, RpcCallback.class);
92  
93          assertEquals(expectedMethodName, method.getName());
94          controller.setFailedOn(failureCause);
95          rpcCallback.run(response);
96  
97          return null;
98        }
99      }).when(rpcChannel).callMethod(
100         any(MethodDescriptor.class), any(RpcController.class), any(Message.class),
101         any(Message.class), any(RpcCallback.class));
102   }
103 
104   @Test
105   public void testPreservedExceptionOnPrepare() {
106     PrepareBulkLoadResponse response = PrepareBulkLoadResponse.newBuilder()
107         .setBulkToken("unused").build();
108     setupMockForMethod("PrepareBulkLoad", response, DNRIOE);
109 
110     try {
111       client.prepareBulkLoad(TableName.valueOf("prepare"));
112     } catch (IOException e) {
113       checkCaughtException(e);
114     }
115   }
116 
117   @Test
118   public void testPreservedExceptionOnCleanup() {
119     CleanupBulkLoadResponse response = CleanupBulkLoadResponse.newBuilder().build();
120     setupMockForMethod("CleanupBulkLoad", response, DNRIOE);
121 
122     try {
123       client.cleanupBulkLoad("unused");
124     } catch (IOException e) {
125       checkCaughtException(e);
126     }
127   }
128 
129   @Test
130   public void testPreservedExceptionOnBulkLoad() {
131     SecureBulkLoadHFilesResponse response = SecureBulkLoadHFilesResponse.newBuilder()
132         .setLoaded(false).build();
133     setupMockForMethod("SecureBulkLoadHFiles", response, DNRIOE);
134 
135     try {
136       client.bulkLoadHFiles(
137           Collections.<Pair<byte[],String>> emptyList(), null, "unused", new byte[0]);
138     } catch (IOException e) {
139       checkCaughtException(e);
140     }
141   }
142 
143   private void checkCaughtException(IOException e) {
144     assertTrue(
145         "Expected the DoNotRetryIOException to be returned without being wrapped by"
146         + " another IOException. Was " + StringUtils.stringifyException(e), e == DNRIOE);
147   }
148 }