Home | History | Annotate | Download | only in elonen
      1 package fi.iki.elonen;
      2 
      3 /*
      4  * #%L
      5  * NanoHttpd-Websocket
      6  * %%
      7  * Copyright (C) 2012 - 2015 nanohttpd
      8  * %%
      9  * Redistribution and use in source and binary forms, with or without modification,
     10  * are permitted provided that the following conditions are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright notice, this
     13  *    list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright notice,
     16  *    this list of conditions and the following disclaimer in the documentation
     17  *    and/or other materials provided with the distribution.
     18  *
     19  * 3. Neither the name of the nanohttpd nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software without
     21  *    specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     31  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     32  * OF THE POSSIBILITY OF SUCH DAMAGE.
     33  * #L%
     34  */
     35 
     36 import static junit.framework.Assert.assertEquals;
     37 import static junit.framework.Assert.assertNotNull;
     38 import static junit.framework.Assert.assertNull;
     39 import static org.mockito.Mockito.when;
     40 
     41 import java.io.IOException;
     42 import java.util.HashMap;
     43 import java.util.Map;
     44 
     45 import org.junit.Before;
     46 import org.junit.Test;
     47 import org.junit.runner.RunWith;
     48 import org.mockito.Mock;
     49 import org.mockito.Mockito;
     50 import org.mockito.runners.MockitoJUnitRunner;
     51 
     52 import fi.iki.elonen.NanoHTTPD.IHTTPSession;
     53 import fi.iki.elonen.NanoHTTPD.Response;
     54 import fi.iki.elonen.NanoWSD.WebSocketFrame;
     55 import fi.iki.elonen.NanoWSD.WebSocketFrame.CloseCode;
     56 
     57 @RunWith(MockitoJUnitRunner.class)
     58 public class WebSocketResponseHandlerTest {
     59 
     60     @Mock
     61     private IHTTPSession session;
     62 
     63     private NanoWSD nanoWebSocketServer;
     64 
     65     private Map<String, String> headers;
     66 
     67     private static class MockedWSD extends NanoWSD {
     68 
     69         public MockedWSD(int port) {
     70             super(port);
     71         }
     72 
     73         public MockedWSD(String hostname, int port) {
     74             super(hostname, port);
     75         }
     76 
     77         @Override
     78         protected WebSocket openWebSocket(IHTTPSession handshake) {
     79             return new WebSocket(handshake) { // Dummy websocket inner class.
     80 
     81                 @Override
     82                 protected void onPong(WebSocketFrame pong) {
     83                 }
     84 
     85                 @Override
     86                 protected void onOpen() {
     87                 }
     88 
     89                 @Override
     90                 protected void onMessage(WebSocketFrame message) {
     91                 }
     92 
     93                 @Override
     94                 protected void onException(IOException exception) {
     95                 }
     96 
     97                 @Override
     98                 protected void onClose(CloseCode code, String reason, boolean initiatedByRemote) {
     99                 }
    100             };
    101         }
    102     }
    103 
    104     @Before
    105     public void setUp() {
    106         this.nanoWebSocketServer = Mockito.mock(MockedWSD.class, Mockito.CALLS_REAL_METHODS);
    107 
    108         this.headers = new HashMap<String, String>();
    109         this.headers.put("upgrade", "websocket");
    110         this.headers.put("connection", "Upgrade");
    111         this.headers.put("sec-websocket-key", "x3JJHMbDL1EzLkh9GBhXDw==");
    112         this.headers.put("sec-websocket-protocol", "chat, superchat");
    113         this.headers.put("sec-websocket-version", "13");
    114 
    115         when(this.session.getHeaders()).thenReturn(this.headers);
    116     }
    117 
    118     @Test
    119     public void testConnectionHeaderHandlesKeepAlive_FixingFirefoxConnectIssue() {
    120         this.headers.put("connection", "keep-alive, Upgrade");
    121         Response handshakeResponse = this.nanoWebSocketServer.serve(this.session);
    122 
    123         assertNotNull(handshakeResponse);
    124     }
    125 
    126     @Test
    127     public void testHandshakeReturnsResponseWithExpectedHeaders() {
    128         Response handshakeResponse = this.nanoWebSocketServer.serve(this.session);
    129 
    130         assertNotNull(handshakeResponse);
    131 
    132         assertEquals(handshakeResponse.getHeader(NanoWSD.HEADER_WEBSOCKET_ACCEPT), "HSmrc0sMlYUkAGmm5OPpG2HaGWk=");
    133         assertEquals(handshakeResponse.getHeader(NanoWSD.HEADER_WEBSOCKET_PROTOCOL), "chat");
    134     }
    135 
    136     @Test
    137     public void testMissingKeyReturnsErrorResponse() {
    138         this.headers.remove("sec-websocket-key");
    139 
    140         Response handshakeResponse = this.nanoWebSocketServer.serve(this.session);
    141 
    142         assertNotNull(handshakeResponse);
    143         assertEquals(Response.Status.BAD_REQUEST, handshakeResponse.getStatus());
    144     }
    145 
    146     @Test
    147     public void testWrongConnectionHeaderReturnsNullResponse() {
    148         this.headers.put("connection", "Junk");
    149         Response handshakeResponse = this.nanoWebSocketServer.serve(this.session);
    150         assertNull(handshakeResponse.getHeader(NanoWSD.HEADER_UPGRADE));
    151     }
    152 
    153     @Test
    154     public void testWrongUpgradeHeaderReturnsNullResponse() {
    155         this.headers.put("upgrade", "not a websocket");
    156         Response handshakeResponse = this.nanoWebSocketServer.serve(this.session);
    157         assertNull(handshakeResponse.getHeader(NanoWSD.HEADER_UPGRADE));
    158     }
    159 
    160     @Test
    161     public void testWrongWebsocketVersionReturnsErrorResponse() {
    162         this.headers.put("sec-websocket-version", "12");
    163 
    164         Response handshakeResponse = this.nanoWebSocketServer.serve(this.session);
    165 
    166         assertNotNull(handshakeResponse);
    167         assertEquals(Response.Status.BAD_REQUEST, handshakeResponse.getStatus());
    168     }
    169 }
    170