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,
    13   *  software distributed under the License is distributed on an
    14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15   *  KIND, either express or implied.  See the License for the
    16   *  specific language governing permissions and limitations
    17   *  under the License.
    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   * Tests {@link RequestResponseFilter}.
    45   *
    46   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
    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          // Set up mock objects.
    70          session = new DummySession();
    71          chain = session.getFilterChain();
    72          nextFilterControl = MockControl.createControl(NextFilter.class);
    73          nextFilter = (NextFilter) nextFilterControl.getMock();
    74
    75          // Initialize the filter.
    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          // Destroy the filter.
    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          // Record
    98          nextFilter.filterWrite(session, new DefaultWriteRequest(req.getMessage()));
    99          nextFilterControl.setMatcher(matcher);
    100         nextFilter.messageSent(session, rwr);
    101         nextFilter.messageReceived(session, res);
    102
    103         // Replay
    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()); // Ignored
    109
    110         // Verify
    111         nextFilterControl.verify();
    112         assertEquals(res, req.awaitResponse());
    113         assertNoSuchElementException(req);
    114     }
    115
    116     private void assertNoSuchElementException(Request req) throws InterruptedException {
    117         // Make sure if an exception is thrown if a user waits one more time.
    118         try {
    119             req.awaitResponse();
    120             fail();
    121         } catch (NoSuchElementException e) {
    122             // Signifies a successful test execution
    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         // Record
    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         // Replay
    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()); // Ignored
    148         filter.messageReceived(nextFilter, session, res2.getMessage()); // Ignored
    149
    150         // Verify
    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); // 10ms timeout
    160         Response res = new Response(req, new Message(1, ResponseType.WHOLE), ResponseType.WHOLE);
    161         WriteRequest rwr = new DefaultWriteRequest(req);
    162
    163         // Record
    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         // Replay
    171         nextFilterControl.replay();
    172         filter.filterWrite(nextFilter, session, rwr);
    173         filter.messageSent(nextFilter, session, matcher.getLastWriteRequest());
    174         Thread.sleep(300); // Wait until the request times out.
    175         filter.messageReceived(nextFilter, session, res.getMessage()); // Ignored
    176
    177         // Verify
    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             // Signifies a successful test execution
    189             assertTrue(true);
    190         }
    191     }
    192
    193     @Test
    194     public void testPartialResponseTimeout() throws Exception {
    195         Request req = new Request(1, new Object(), 10); // 10ms timeout
    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         // Record
    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         // Replay
    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); // Wait until the request times out.
    214         filter.messageReceived(nextFilter, session, res2.getMessage()); // Ignored
    215         filter.messageReceived(nextFilter, session, res1.getMessage()); // Ignored
    216
    217         // Verify
    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         // We run a test case that doesn't raise a timeout to make sure
    227         // the timeout is not raised again by disconnection.
    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         // Record
    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         // Replay
    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         // Verify
    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          * Default constructor
    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          * Default constructor
    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 }