1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.http.impl.execchain;
28
29 import org.apache.http.Header;
30 import org.apache.http.HttpEntityEnclosingRequest;
31 import org.apache.http.HttpHost;
32 import org.apache.http.client.HttpRequestRetryHandler;
33 import org.apache.http.client.NonRepeatableRequestException;
34 import org.apache.http.client.entity.EntityBuilder;
35 import org.apache.http.client.methods.HttpExecutionAware;
36 import org.apache.http.client.methods.HttpGet;
37 import org.apache.http.client.methods.HttpPost;
38 import org.apache.http.client.methods.HttpRequestWrapper;
39 import org.apache.http.client.protocol.HttpClientContext;
40 import org.apache.http.conn.routing.HttpRoute;
41 import org.apache.http.protocol.HttpContext;
42 import org.junit.Assert;
43 import org.junit.Before;
44 import org.junit.Test;
45 import org.mockito.Mock;
46 import org.mockito.Mockito;
47 import org.mockito.MockitoAnnotations;
48 import org.mockito.invocation.InvocationOnMock;
49 import org.mockito.stubbing.Answer;
50
51 import java.io.ByteArrayInputStream;
52 import java.io.ByteArrayOutputStream;
53 import java.io.IOException;
54
55 @SuppressWarnings({"boxing","static-access"})
56 public class TestRetryExec {
57
58 @Mock
59 private ClientExecChain requestExecutor;
60 @Mock
61 private HttpRequestRetryHandler retryHandler;
62 @Mock
63 private HttpExecutionAware execAware;
64
65 private RetryExec retryExec;
66 private HttpHost target;
67
68 @Before
69 public void setup() throws Exception {
70 MockitoAnnotations.initMocks(this);
71 retryExec = new RetryExec(requestExecutor, retryHandler);
72 target = new HttpHost("localhost", 80);
73 }
74
75 @Test(expected = IOException.class)
76 public void testFundamentals() throws Exception {
77 final HttpRoute route = new HttpRoute(target);
78 final HttpGet get = new HttpGet("/test");
79 get.addHeader("header", "this");
80 get.addHeader("header", "that");
81 final HttpRequestWrapper request = HttpRequestWrapper.wrap(get);
82 final HttpClientContext context = HttpClientContext.create();
83
84 Mockito.when(requestExecutor.execute(
85 Mockito.eq(route),
86 Mockito.same(request),
87 Mockito.<HttpClientContext>any(),
88 Mockito.<HttpExecutionAware>any())).thenAnswer(new Answer<Object>() {
89
90 @Override
91 public Object answer(final InvocationOnMock invocationOnMock) throws Throwable {
92 final Object[] args = invocationOnMock.getArguments();
93 final HttpRequestWrapper wrapper = (HttpRequestWrapper) args[1];
94 final Header[] headers = wrapper.getAllHeaders();
95 Assert.assertEquals(2, headers.length);
96 Assert.assertEquals("this", headers[0].getValue());
97 Assert.assertEquals("that", headers[1].getValue());
98 wrapper.addHeader("Cookie", "monster");
99 throw new IOException("Ka-boom");
100 }
101
102 });
103 Mockito.when(retryHandler.retryRequest(
104 Mockito.<IOException>any(),
105 Mockito.eq(1),
106 Mockito.<HttpContext>any())).thenReturn(Boolean.TRUE);
107 try {
108 retryExec.execute(route, request, context, execAware);
109 } catch (final IOException ex) {
110 Mockito.verify(requestExecutor, Mockito.times(2)).execute(
111 Mockito.eq(route),
112 Mockito.same(request),
113 Mockito.same(context),
114 Mockito.same(execAware));
115 throw ex;
116 }
117 }
118
119 @Test(expected = IOException.class)
120 public void testAbortedRequest() throws Exception {
121 final HttpRoute route = new HttpRoute(target);
122 final HttpGet get = new HttpGet("/test");
123 final HttpRequestWrapper request = HttpRequestWrapper.wrap(get);
124 final HttpClientContext context = HttpClientContext.create();
125
126 Mockito.when(requestExecutor.execute(
127 Mockito.eq(route),
128 Mockito.same(request),
129 Mockito.<HttpClientContext>any(),
130 Mockito.<HttpExecutionAware>any())).thenThrow(new IOException("Ka-boom"));
131
132 Mockito.when(execAware.isAborted()).thenReturn(Boolean.TRUE);
133 try {
134 retryExec.execute(route, request, context, execAware);
135 } catch (final IOException ex) {
136 Mockito.verify(requestExecutor, Mockito.times(1)).execute(
137 Mockito.eq(route),
138 Mockito.same(request),
139 Mockito.same(context),
140 Mockito.same(execAware));
141 Mockito.verify(retryHandler, Mockito.never()).retryRequest(
142 Mockito.<IOException>any(),
143 Mockito.anyInt(),
144 Mockito.<HttpContext>any());
145
146 throw ex;
147 }
148 }
149
150 @Test(expected = NonRepeatableRequestException.class)
151 public void testNonRepeatableRequest() throws Exception {
152 final HttpRoute route = new HttpRoute(target);
153 final HttpPost post = new HttpPost("/test");
154 post.setEntity(EntityBuilder.create()
155 .setStream(new ByteArrayInputStream(new byte[]{}))
156 .build());
157 final HttpRequestWrapper request = HttpRequestWrapper.wrap(post);
158 final HttpClientContext context = HttpClientContext.create();
159
160 Mockito.when(requestExecutor.execute(
161 Mockito.eq(route),
162 Mockito.same(request),
163 Mockito.<HttpClientContext>any(),
164 Mockito.<HttpExecutionAware>any())).thenAnswer(new Answer<Object>() {
165
166 @Override
167 public Object answer(final InvocationOnMock invocationOnMock) throws Throwable {
168 final Object[] args = invocationOnMock.getArguments();
169 final HttpEntityEnclosingRequest req = (HttpEntityEnclosingRequest) args[1];
170 req.getEntity().writeTo(new ByteArrayOutputStream());
171 throw new IOException("Ka-boom");
172 }
173
174 });
175 Mockito.when(retryHandler.retryRequest(
176 Mockito.<IOException>any(),
177 Mockito.eq(1),
178 Mockito.<HttpContext>any())).thenReturn(Boolean.TRUE);
179 try {
180 retryExec.execute(route, request, context, execAware);
181 } catch (final IOException ex) {
182 Mockito.verify(requestExecutor, Mockito.times(1)).execute(
183 Mockito.eq(route),
184 Mockito.same(request),
185 Mockito.same(context),
186 Mockito.same(execAware));
187
188 throw ex;
189 }
190 }
191
192 }