• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
MockedWSD(int port)69         public MockedWSD(int port) {
70             super(port);
71         }
72 
MockedWSD(String hostname, int port)73         public MockedWSD(String hostname, int port) {
74             super(hostname, port);
75         }
76 
77         @Override
openWebSocket(IHTTPSession handshake)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
setUp()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
testConnectionHeaderHandlesKeepAlive_FixingFirefoxConnectIssue()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
testHandshakeReturnsResponseWithExpectedHeaders()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
testMissingKeyReturnsErrorResponse()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
testWrongConnectionHeaderReturnsNullResponse()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
testWrongUpgradeHeaderReturnsNullResponse()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
testWrongWebsocketVersionReturnsErrorResponse()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