1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.filter.reqres;
21
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
26
27 import java.util.NoSuchElementException;
28 import java.util.concurrent.Executors;
29 import java.util.concurrent.ScheduledExecutorService;
30
31 import org.apache.mina.core.filterchain.IoFilterChain;
32 import org.apache.mina.core.filterchain.IoFilter.NextFilter;
33 import org.apache.mina.core.session.DummySession;
34 import org.apache.mina.core.session.IoSession;
35 import org.apache.mina.core.write.DefaultWriteRequest;
36 import org.apache.mina.core.write.WriteRequest;
37 import org.easymock.AbstractMatcher;
38 import org.easymock.MockControl;
39 import org.junit.After;
40 import org.junit.Before;
41 import org.junit.Test;
42
43
44
45
46
47
48 public class RequestResponseFilterTest {
49
50 private ScheduledExecutorService scheduler;
51
52 private RequestResponseFilter filter;
53
54 private IoSession session;
55
56 private IoFilterChain chain;
57
58 private NextFilter nextFilter;
59
60 private MockControl nextFilterControl;
61
62 private final WriteRequestMatcher matcher = new WriteRequestMatcher();
63
64 @Before
65 public void setUp() throws Exception {
66 scheduler = Executors.newScheduledThreadPool(1);
67 filter = new RequestResponseFilter(new MessageInspector(), scheduler);
68
69
70 session = new DummySession();
71 chain = session.getFilterChain();
72 nextFilterControl = MockControl.createControl(NextFilter.class);
73 nextFilter = (NextFilter) nextFilterControl.getMock();
74
75
76 filter.onPreAdd(chain, "reqres", nextFilter);
77 filter.onPostAdd(chain, "reqres", nextFilter);
78 assertFalse(session.getAttributeKeys().isEmpty());
79 }
80
81 @After
82 public void tearDown() throws Exception {
83
84 filter.onPreRemove(chain, "reqres", nextFilter);
85 filter.onPostRemove(chain, "reqres", nextFilter);
86 filter.destroy();
87 filter = null;
88 scheduler.shutdown();
89 }
90
91 @Test
92 public void testWholeResponse() throws Exception {
93 Request req = new Request(1, new Object(), Long.MAX_VALUE);
94 Response res = new Response(req, new Message(1, ResponseType.WHOLE), ResponseType.WHOLE);
95 WriteRequest rwr = new DefaultWriteRequest(req);
96
97
98 nextFilter.filterWrite(session, new DefaultWriteRequest(req.getMessage()));
99 nextFilterControl.setMatcher(matcher);
100 nextFilter.messageSent(session, rwr);
101 nextFilter.messageReceived(session, res);
102
103
104 nextFilterControl.replay();
105 filter.filterWrite(nextFilter, session, rwr);
106 filter.messageSent(nextFilter, session, matcher.getLastWriteRequest());
107 filter.messageReceived(nextFilter, session, res.getMessage());
108 filter.messageReceived(nextFilter, session, res.getMessage());
109
110
111 nextFilterControl.verify();
112 assertEquals(res, req.awaitResponse());
113 assertNoSuchElementException(req);
114 }
115
116 private void assertNoSuchElementException(Request req) throws InterruptedException {
117
118 try {
119 req.awaitResponse();
120 fail();
121 } catch (NoSuchElementException e) {
122
123 assertTrue(true);
124 }
125 }
126
127 @Test
128 public void testPartialResponse() throws Exception {
129 Request req = new Request(1, new Object(), Long.MAX_VALUE);
130 Response res1 = new Response(req, new Message(1, ResponseType.PARTIAL), ResponseType.PARTIAL);
131 Response res2 = new Response(req, new Message(1, ResponseType.PARTIAL_LAST), ResponseType.PARTIAL_LAST);
132 WriteRequest rwr = new DefaultWriteRequest(req);
133
134
135 nextFilter.filterWrite(session, new DefaultWriteRequest(req.getMessage()));
136 nextFilterControl.setMatcher(matcher);
137 nextFilter.messageSent(session, rwr);
138 nextFilter.messageReceived(session, res1);
139 nextFilter.messageReceived(session, res2);
140
141
142 nextFilterControl.replay();
143 filter.filterWrite(nextFilter, session, rwr);
144 filter.messageSent(nextFilter, session, matcher.getLastWriteRequest());
145 filter.messageReceived(nextFilter, session, res1.getMessage());
146 filter.messageReceived(nextFilter, session, res2.getMessage());
147 filter.messageReceived(nextFilter, session, res1.getMessage());
148 filter.messageReceived(nextFilter, session, res2.getMessage());
149
150
151 nextFilterControl.verify();
152 assertEquals(res1, req.awaitResponse());
153 assertEquals(res2, req.awaitResponse());
154 assertNoSuchElementException(req);
155 }
156
157 @Test
158 public void testWholeResponseTimeout() throws Exception {
159 Request req = new Request(1, new Object(), 10);
160 Response res = new Response(req, new Message(1, ResponseType.WHOLE), ResponseType.WHOLE);
161 WriteRequest rwr = new DefaultWriteRequest(req);
162
163
164 nextFilter.filterWrite(session, new DefaultWriteRequest(req.getMessage()));
165 nextFilterControl.setMatcher(matcher);
166 nextFilter.messageSent(session, rwr);
167 nextFilter.exceptionCaught(session, new RequestTimeoutException(req));
168 nextFilterControl.setMatcher(new ExceptionMatcher());
169
170
171 nextFilterControl.replay();
172 filter.filterWrite(nextFilter, session, rwr);
173 filter.messageSent(nextFilter, session, matcher.getLastWriteRequest());
174 Thread.sleep(300);
175 filter.messageReceived(nextFilter, session, res.getMessage());
176
177
178 nextFilterControl.verify();
179 assertRequestTimeoutException(req);
180 assertNoSuchElementException(req);
181 }
182
183 private void assertRequestTimeoutException(Request req) throws InterruptedException {
184 try {
185 req.awaitResponse();
186 fail();
187 } catch (RequestTimeoutException e) {
188
189 assertTrue(true);
190 }
191 }
192
193 @Test
194 public void testPartialResponseTimeout() throws Exception {
195 Request req = new Request(1, new Object(), 10);
196 Response res1 = new Response(req, new Message(1, ResponseType.PARTIAL), ResponseType.PARTIAL);
197 Response res2 = new Response(req, new Message(1, ResponseType.PARTIAL_LAST), ResponseType.PARTIAL_LAST);
198 WriteRequest rwr = new DefaultWriteRequest(req);
199
200
201 nextFilter.filterWrite(session, new DefaultWriteRequest(req.getMessage()));
202 nextFilterControl.setMatcher(matcher);
203 nextFilter.messageSent(session, rwr);
204 nextFilter.messageReceived(session, res1);
205 nextFilter.exceptionCaught(session, new RequestTimeoutException(req));
206 nextFilterControl.setMatcher(new ExceptionMatcher());
207
208
209 nextFilterControl.replay();
210 filter.filterWrite(nextFilter, session, rwr);
211 filter.messageSent(nextFilter, session, matcher.getLastWriteRequest());
212 filter.messageReceived(nextFilter, session, res1.getMessage());
213 Thread.sleep(300);
214 filter.messageReceived(nextFilter, session, res2.getMessage());
215 filter.messageReceived(nextFilter, session, res1.getMessage());
216
217
218 nextFilterControl.verify();
219 assertEquals(res1, req.awaitResponse());
220 assertRequestTimeoutException(req);
221 assertNoSuchElementException(req);
222 }
223
224 @Test
225 public void testTimeoutByDisconnection() throws Exception {
226
227
228 testWholeResponse();
229 nextFilterControl.reset();
230
231 Request req1 = new Request(1, new Object(), Long.MAX_VALUE);
232 Request req2 = new Request(2, new Object(), Long.MAX_VALUE);
233 WriteRequest rwr1 = new DefaultWriteRequest(req1);
234 WriteRequest rwr2 = new DefaultWriteRequest(req2);
235
236
237 nextFilter.filterWrite(session, new DefaultWriteRequest(req1.getMessage()));
238 nextFilterControl.setMatcher(matcher);
239 nextFilter.messageSent(session, rwr1);
240 nextFilter.filterWrite(session, new DefaultWriteRequest(req2.getMessage()));
241 nextFilter.messageSent(session, rwr2);
242 nextFilter.exceptionCaught(session, new RequestTimeoutException(req1));
243 nextFilterControl.setMatcher(new ExceptionMatcher());
244 nextFilter.exceptionCaught(session, new RequestTimeoutException(req2));
245 nextFilter.sessionClosed(session);
246
247
248 nextFilterControl.replay();
249 filter.filterWrite(nextFilter, session, rwr1);
250 filter.messageSent(nextFilter, session, matcher.getLastWriteRequest());
251 filter.filterWrite(nextFilter, session, rwr2);
252 filter.messageSent(nextFilter, session, matcher.getLastWriteRequest());
253 filter.sessionClosed(nextFilter, session);
254
255
256 nextFilterControl.verify();
257 assertRequestTimeoutException(req1);
258 assertRequestTimeoutException(req2);
259 }
260
261 static class Message {
262 private final int id;
263
264 private final ResponseType type;
265
266 Message(int id, ResponseType type) {
267 this.id = id;
268 this.type = type;
269 }
270
271 public int getId() {
272 return id;
273 }
274
275 public ResponseType getType() {
276 return type;
277 }
278 }
279
280 private static class MessageInspector implements ResponseInspector {
281
282
283
284 public MessageInspector() {
285 super();
286 }
287
288 public Object getRequestId(Object message) {
289 if (!(message instanceof Message)) {
290 return null;
291 }
292
293 return ((Message) message).getId();
294 }
295
296 public ResponseType getResponseType(Object message) {
297 if (!(message instanceof Message)) {
298 return null;
299 }
300
301 return ((Message) message).getType();
302 }
303 }
304
305 private static class WriteRequestMatcher extends AbstractMatcher {
306 private WriteRequest lastWriteRequest;
307
308
309
310
311 public WriteRequestMatcher() {
312 super();
313 }
314
315 public WriteRequest getLastWriteRequest() {
316 return lastWriteRequest;
317 }
318
319 @Override
320 protected boolean argumentMatches(Object expected, Object actual) {
321 if (actual instanceof WriteRequest && expected instanceof WriteRequest) {
322 boolean answer = ((WriteRequest) expected).getMessage().equals(((WriteRequest) actual).getMessage());
323 lastWriteRequest = (WriteRequest) actual;
324 return answer;
325 }
326 return super.argumentMatches(expected, actual);
327 }
328 }
329
330 static class ExceptionMatcher extends AbstractMatcher {
331 @Override
332 protected boolean argumentMatches(Object expected, Object actual) {
333 if (actual instanceof RequestTimeoutException && expected instanceof RequestTimeoutException) {
334 return ((RequestTimeoutException) expected).getRequest().equals(
335 ((RequestTimeoutException) actual).getRequest());
336 }
337 return super.argumentMatches(expected, actual);
338 }
339 }
340 }